我正在使用MS HttpClient
ASP.NET Web API Client Libraries。ProgressMessageHandler
我很高兴在控制台应用程序中对此进行了修补,没有问题,但现在在 WinForm 应用程序中,“发布”任务只是简单地卡在了.Wait()
或.Result
.
下面是我非常简单的测试应用程序的完整列表。按钮 1 工作正常,按钮 2 每次调用时都会冻结postTask.Result
。为什么?
定位 4.0 或 4.5 没有区别。控制台应用程序中的相同代码没有问题。
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Handlers;
using System.Windows.Forms;
namespace WindowsFormsApplication13
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private ProgressMessageHandler _progressHandler = new ProgressMessageHandler();
private const string SERVICE_URL = "http://www.google.com.au";
private HttpClient GetClient(bool includeProgressHandler = false)
{
var handlers = new List<DelegatingHandler>();
if (includeProgressHandler)
{
handlers.Add(_progressHandler);
}
var client = HttpClientFactory.Create(handlers.ToArray());
client.BaseAddress = new Uri(SERVICE_URL);
return client;
}
private void PostUsingClient(HttpClient client)
{
var postTask = client.PostAsJsonAsync("test", new
{
Foo = "Bar"
});
var postResult = postTask.Result;
MessageBox.Show("OK");
}
private void button1_Click(object sender, EventArgs e)
{
using (var client = GetClient())
{
PostUsingClient(client);
}
}
private void button2_Click(object sender, EventArgs e)
{
using (var client = GetClient(true))
{
PostUsingClient(client);
}
}
}
}
更新
好的,所以看起来这是我的问题。对于 .NET 4.5,显而易见的解决方案是,正如 @StephenCleary 建议的那样,让 async / await 模式从PostAsJsonAsync
调用一直渗透到按钮单击处理程序中。更像这样的东西:
private Task<HttpResponseMessage> PostUsingClient(HttpClient client)
{
return client.PostAsJsonAsync("test", new
{
Foo = "Bar"
});
}
private async void button2_Click(object sender, EventArgs e)
{
var client = GetClient(true);
var response = await PostUsingClient(client);
}
现在我的问题是在 .NET 4.0 中获得等效的解决方案(当然,出于遗留原因)。一个接近的近似值是在按钮单击处理程序中使用延续,麻烦是(再次出于遗留原因),我实际上希望按钮单击处理程序阻塞,直到异步返回。我找到了一些使用 4.0 兼容yield
运算符的创造性解决方案,但它们感觉有点乱。相反,我可以设计的最简单的替代方案是:
private void button2_Click(object sender, EventArgs e)
{
var result = Task.Run(() => { return PostUsingClient(client); }).Result;
}
我无法想象这是最高效的实现,坦率地说它仍然感觉很笨拙。我能做得更好吗?