Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async httpclient operation

I am trying to design a browser that will fetch site updates programmatically. I am trying to do this with async/await methods but when I try and run the program it seems to just hang on response.Wait();. not sure why or whats happening.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var urls = sourceUrls();
        Task<HttpResponseMessage> response = login(urls[0]);
        response.Wait();

        Console.Write( "Complete" );

    }

    private List<Site> sourceUrls()
    {

        var urls = new List<Site>();
        urls.Add(new Site("http://yahoo.com", "test", "test"));

        return urls;
    }
}

browser class::

static public class Browser
{

    private static CookieContainer cc = new CookieContainer();
    private static HttpClientHandler handler = new HttpClientHandler();
    public static HttpClient browser = new HttpClient(handler);

    static Browser()
    {
        handler.CookieContainer = cc;
    }


    static public async Task<HttpResponseMessage> login(Site site)
    {
        var _postData = new Dictionary<string, string>
        {
            {"test", "test"}
        };

        FormUrlEncodedContent postData = new FormUrlEncodedContent(_postData);
        HttpResponseMessage response = await browser.PostAsync(site.url, postData);
        return response;
    }
}

Also, for my intended purposes, is it ok to make browser a static function, or does that not make sense? Sorry for the questions, new to c#

like image 904
cubesnyc Avatar asked Oct 31 '22 23:10

cubesnyc


1 Answers

It's a bad idea to call Wait on a Task in a UI thread, it results in a deadlock. You can simply await the response which will achieve what you want. The await unwraps the response from the Task so your return type is now just HttpResponseMessage. Because you can't mark constructors as async you can move the functionality to another method that kicks off the operation.

public MainWindow()
{
    InitializeComponent();
    LoadUrlsAsync();
}

public async Task LoadUrlsAsync()
{
    var urls = sourceUrls();
    HttpResponseMessage response = await login(urls[0]);

    Console.Write( "Complete" );
}

See this article for best practices when using async/await.

Alternatively you can use the Task.ConfigureAwait extension method to configure the continuation not to run on the current SyncrhronizationContext which should also avoid the deadlock.

public MainWindow()
{
    InitializeComponent();

    var urls = sourceUrls();
    Task<HttpResponseMessage> response = login(urls[0]).ConfigureAwait(false);
    response.Wait();

    Console.Write( "Complete" );
}
like image 169
NeddySpaghetti Avatar answered Nov 15 '22 05:11

NeddySpaghetti