Are there any issues with my multithreaded HttpClient?

后端 未结 4 1824
走了就别回头了
走了就别回头了 2021-02-04 16:47

So after dabbling with Java and HttpClient, I\'ve decided to transition to C# to try and lower the memory usage while increasing speed. I\'ve been reading tons of articles provi

相关标签:
4条回答
  • 2021-02-04 17:25

    The following methods are thread-safe:

    CancelPendingRequests
    DeleteAsync
    GetAsync
    GetByteArrayAsync
    GetStreamAsync
    GetStringAsync
    PostAsync
    PutAsync
    SendAsync
    

    More details:

    • Is HttpClient safe to use concurrently?
    • http://blogs.msdn.com/b/henrikn/archive/2012/08/07/httpclient-httpclienthandler-and-httpwebrequesthandler.aspx
    0 讨论(0)
  • 2021-02-04 17:26

    Here is how I would do it if I were you. I would leverage async as much as possible as it's much more efficient than using Threads (you most likely won't have to context-switch all the time which is expensive).

    class MainClass
    {
        public static HttpClient client = new HttpClient();
        static string url = "http://www.website.com";
    
        public static async Task getSessionAsync()
        {
            StringContent queryString = new StringContent("{json:here}");
    
            // Send a request asynchronously continue when complete
            using (HttpResponseMessage result = await client.PostAsync(url, queryString))
            {
                // Check for success or throw exception
                string resultContent = await result.Content.ReadAsStringAsync();
                Console.WriteLine(resultContent);
            }
        }
    
        public static async Task RunAsync()
        {
            await getSessionAsync();
            // Not yet implemented yet..
            //doMore ();
        }
    
        public static void Main(string[] args)
        {
            Console.WriteLine("Welcome!");
    
            const int parallelRequests = 5;
            // Send the request X times in parallel
            Task.WhenAll(Enumerable.Range(1, parallelRequests).Select(i => RunAsync())).GetAwaiter().GetResult();
    
            // It would be better to do Task.WhenAny() in a while loop until one of the task succeeds
            // We could add cancellation of other tasks once we get a successful response
        }
    }
    

    Note that I do agree with @Damien_The_Unbeliever: if the server has issues under heavy load, you shouldn't be adding unnecessary load (doing X times the same request) and contribute to the server's issues. Ideally you'd fix the server code but I can understand that it's not yours.

    0 讨论(0)
  • 2021-02-04 17:27

    Messing with the headers is not thread safe.

    For example, swapping out an OAuth access token with a new one is not thread safe. Facing this right now with a Xamarin mobile app. I have a crash report where one thread was modifying headers while another thread was attempting a request.

    0 讨论(0)
  • 2021-02-04 17:40

    Reading the docummentation of HttpClient:

    Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

    Don't take risks. Have a separate HTTP client per thread.

    It seems that you are blocking the thread waiting for the reply and you are doing it from a thread that does not do anything extra. Then why bother with async/await? You can use plain simple blocking calls.

    Also - your program now finishes immediately after starting the threads. You might want to wait for the threads to finish before returning from main. You can do that by this code at the end of your program:

    Thread1.Join();
    Thread2.Join();
    

    Update based on comments:

    1. Decide how many parallel requests you want to make - this will be your number of threads.
    2. Make main thread wait for signal using ManualResetEvent.
    3. In each thread keep submitting your requests. As soon as you get answer that you are waiting for - signal the ManualResetEvent and allow your main function to return.
    0 讨论(0)
提交回复
热议问题