如何将异步HttpClient响应返回给WinForm?

时间:2017-07-13 19:17:54

标签: c# .net async-await dotnet-httpclient

到目前为止,我一直在WinForms应用程序中进行同步HttpWebRequest调用。我想以异步方式开始这样做,以便不阻止UI线程并让它挂起。因此,我试图切换到HttpClient,但我也是异步和任务的新手,但还没有完全理解它。

我可以启动请求并获取响应并隔离我想要的数据(结果,reasonPhrase,标题,代码)但不知道如何将其返回以便在textBox1中显示。如果发生超时或无法连接消息,我还需要捕获ex.message并返回到表单。

我看到的每一个例子都在可用的时候将值写入Console.WriteLine(),但我需要将它们返回到表单进行显示和处理,并且很难理解如何。

这是一个简单的例子:

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.
                }
            }
        }
    }
}

任何有用的提示或建议?

1 个答案:

答案 0 :(得分:9)

创建一个模型来保存您想要返回的数据

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; }
}

避免使用async void方法。将方法转换为async Task并在允许它的事件处理程序中调用它。

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;
}

每次调用下载时都不应创建HttpClient

请参阅What is the overhead of creating a new HttpClient per call in a WebAPI client?