restsharp / RestSharp

Simple REST and HTTP API Client for .NET
https://restsharp.dev
Apache License 2.0
9.6k stars 2.34k forks source link

ThreadPool hang #2083

Open light-years-run opened 1 year ago

light-years-run commented 1 year ago

Describe the bug I use request url in ThreadPool, min Threads set to 2,Max Threads set to 10,when i run my code , after ExecuteGet i got hang,nothing response happen

RestSharp version 110.2.0, Net Framwork version:4.7.1

To Reproduce here is my code

void GetMsg(object line)
        {
            string player = (string)line;

            Console.WriteLine(player);

            string tocken = "Bearer QVQxOjMuMDozLjA6MjQwOnlkU0diS0VXdTV3ZXRYdDVwQzNvUFFhSFlTOFpGVkUwZHh0Ojc4MzY1OnFvc2Z1"

            string url = "https://service-aggregation-layer.juno.ea.com/graphql";

            url += "?variables={%22searchText%22%3A%22" + player.Replace("@", "%40") + "%22%2C%22pageNumber%22%3A1%2C%22pageSize%22%3A20}&extensions={%22persistedQuery%22%3A{%22version%22%3A1%2C%22sha256Hash%22%3A%2283da6f3045ee524f6cb62a1c23eea908c9432f15e87b30dd33b89974ff83c657%22}}&operationName=SearchPlayer";

            RestClient client = new RestClient(url);
            RestRequest request = new RestRequest("");
            request.AddHeader("Authorization", tocken);
            request.AddHeader("Sec-Fetch-Site", "same-site");
            request.AddHeader("Accept", "*/*");
            request.AddHeader("Host", "service-aggregation-layer.juno.ea.com");
            request.AddHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.2 Chrome/83.0.4103.122 Safari/537.36 Origin/10.6.0.00000 EAApp/12.164.0.5421");

            RestResponse response = client.ExecuteGet(request);

            if (response == null || response.Content == null || response.Content == "" || response.Content.Contains("Error"))
            {
                //signal
                countdown.Signal();
                return;
            }

            ResultInfo retInfo = JsonConvert.DeserializeObject<ResultInfo>(response.Content, serializerSettings);

            List<items> all = retInfo.data.players.items;
            if (all.Count > 0)
            {
                mutex.WaitOne();
                content += (string)line;
                string displayName = all[0].displayName;
                content += "----" + displayName;
                content += Environment.NewLine;
                mutex.ReleaseMutex();
            }
            //signal
            countdown.Signal();
        }
        private void btnStart_Click(object sender, EventArgs e)
        {

            int maxCnt = int.Parse(tbxMaxThreadCount.Text);

            ThreadPool.SetMinThreads(2, 2);
            ThreadPool.SetMaxThreads(10, 10);

            string[] allLines = File.ReadAllLines("./msg.txt");

            countdown = new CountdownEvent(allLines.Length);
            foreach (string line in allLines)
            {

                ThreadPool.QueueUserWorkItem(new WaitCallback(GetMsg), line);
            }

            // all done
            countdown.Wait();

            //write to file
            File.WriteAllText("./out.txt", content);
            MessageBox.Show("all done");
        }

Stack trace Copy the full stack trace here if you get an exception.

Desktop (please complete the following information):

Additional context Add any other context about the problem here.

rassilon commented 7 months ago

This seems like a classic case of artificial bounds on thread pool max thread size ends up causing a deadlock of some sort due to async keyword usage and the synchronous methods not actually being synchronous internally (somehow)..

i.e. something like this might be happening:

This is a basic async or distributed processing system issue that can occur when the interfaces to constrained systems don't have built-in support for providing back pressure to the callers. (which isn't easy to do or easy to use once accomplished)

This also might be exacerbated by #2160, but I'm not sure there's necessarily a lot the RestSharp developers should do in this area above and beyond #2160.

vocko commented 4 months ago

We've just noticed the same issue on .NET 4.8 with synchronous calls.

var response = _restClient.Get(request);

The thread just hangs and keeps chewing memory until it causes the instance to crash.

We have replaced it with the

var response = _restClient.ExecuteRequest(request);

and it works fine.

Not sure what's the difference internally but might worth to remove synchronous method specific overloads (if finding out the issue proves too complicated).

I suppose it has something to do with the thread synchronisation and would be great if we can use the async calls but this is a legacy app and refactoring is just not worth it.