Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return async HttpClient responses back to WinForm?

Up until now, I've been making synchronous HttpWebRequest calls in WinForms applications. I want to start doing it asynchronously so as to not block the UI thread and have it hang. Therefore, I am attempting to switch to HttpClient, but I am also new to async and tasks and don't quite get it, yet.

I can launch the request and get a response and isolate the data I want (result, reasonPhrase, headers, code) but don't know how to get that back for display in textBox1. I also need to capture ex.message and return to the form if a timeout or cannot connect message occurs.

Every single example I see has the values written to Console.WriteLine() at the point they are available, but I need them returned back to the form for display and processing and have a hard time understanding how.

Here's a simple example:

namespace AsyncHttpClientTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text = "calling Test()...\r\n";
            DownloadPageAsync();

            // need to get from DownloadPageAsync here: result, reasonPhrase, headers, code 

            textBox1.AppendText("done Test()\r\n");
        }
        static async void DownloadPageAsync()
        {
            // ... Use HttpClient.
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    using (HttpResponseMessage response = await client.GetAsync(new Uri("http://192.168.2.70/")))
                    {
                        using (HttpContent content = response.Content)
                        {
                            // need these to return to Form for display
                            string result = await content.ReadAsStringAsync();
                            string reasonPhrase = response.ReasonPhrase;
                            HttpResponseHeaders headers = response.Headers;
                            HttpStatusCode code = response.StatusCode;
                        }
                    }
                }
                catch (Exception ex)
                {
                    // need to return ex.message for display.
                }
            }
        }
    }
}

Any helpful hints or advice?

like image 534
LordChariot Avatar asked Jul 13 '17 19:07

LordChariot


People also ask

What does PostAsync return?

PostAsync(String, HttpContent)Send a POST request to the specified Uri as an asynchronous operation.

What does HttpClient GetAsync return?

The HTTP request is sent out, and HttpClient. GetAsync returns an uncompleted Task . AsyncAwait_GetSomeDataAsync awaits the Task ; since it is not complete, AsyncAwait_GetSomeDataAsync returns an uncompleted Task . Test5Controller. Get blocks the current thread until that Task completes.

How HttpClient works in c#?

The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.

Can I use Web API in Windows application?

Now, we can create a Winform application to consume the Web API and upload/download the files from web server to our local machine. Open Visual Studio 2015. Click New >> Project >> Visual C# >> Windows >> select Windows Forms Application. Enter your project name and click OK.


1 Answers

create a model to hold the data you want to return

public class DownloadPageAsyncResult {
    public string result { get; set; } 
    public string reasonPhrase { get; set; } 
    public HttpResponseHeaders headers { get; set; }
    public HttpStatusCode code { get; set; }
    public string errorMessage { get; set; }
}

Avoid using async void methods. Convert the method to async Task and call it in the event handler where it is allowed.

private async void button1_Click(object sender, EventArgs e) {
    textBox1.Text = "calling Test()...\r\n";
    var result = await DownloadPageAsync();

    // Access result, reasonPhrase, headers, code here

    textBox1.AppendText("done Test()\r\n");
}

static HttpClient client = new HttpClient();
static async Task<DownloadPageAsyncResult> DownloadPageAsync() {
    var result = new DownloadPageAsyncResult();
    try {
        using (HttpResponseMessage response = await client.GetAsync(new Uri("http://192.168.2.70/"))) {
            using (HttpContent content = response.Content) {
                // need these to return to Form for display
                string resultString = await content.ReadAsStringAsync();
                string reasonPhrase = response.ReasonPhrase;
                HttpResponseHeaders headers = response.Headers;
                HttpStatusCode code = response.StatusCode;                    

                result.result = resultString;
                result.reasonPhrase = reasonPhrase;
                result.headers = headers;
                result.code = code;
            }
        }
    } catch (Exception ex) {
        // need to return ex.message for display.
        result.errorMessage = ex.Message;
    }
    return result;
}

The HttpClientshould also not be created every time the download is called.

Refer to What is the overhead of creating a new HttpClient per call in a WebAPI client?

like image 101
Nkosi Avatar answered Oct 09 '22 00:10

Nkosi