【发布时间】:2020-08-20 21:23:58
【问题描述】:
我编写了一个小的 winforms 应用程序,它将 http 请求发送到我本地网络中的每个 IP 地址,以发现我的某个设备。在我的特定子网掩码上,那是 512 个地址。我已经使用 backGroundWorker 编写了这个,但我想尝试 httpClient 和 Async/Await 模式来实现相同的目标。下面的代码使用一个 httpClient 实例,我一直等到所有请求都完成。这个问题是主线程被阻塞了。我知道这一点是因为我有一个图片框 + 加载 gif 并且它的动画不统一。我按照建议 here 将 GetAsync 方法放在 Task.Run 中,但这也不起作用。
private async void button1_Click(object sender, EventArgs e)
{
var addresses = networkUtils.generateIPRange..
await MakeMultipleHttpRequests(addresses);
}
public async Task MakeMultipleHttpRequests(IPAddress[] addresses)
{
List<Task<HttpResponseMessage>> httpTasks = new List<Task<HttpResponseMessage>>();
foreach (var address in addresses)
{
Task<HttpResponseMessage> response = MakeHttpGetRequest(address.ToString());
httpTasks.Add(response);
}
try
{
if (httpTasks.ToArray().Length != 0)
{
await Task.WhenAll(httpTasks.ToArray());
}
}
catch (Exception ex)
{
Console.WriteLine("\thttp tasks did not complete Exception : {0}", ex.Message);
}
}
private async Task<HttpResponseMessage> MakeHttpGetRequest(string address)
{
var url = string.Format("http://{0}/getStatus", address);
var cts = new System.Threading.CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(10));
HttpResponseMessage response = null;
var request = new HttpRequestMessage(HttpMethod.Get, url);
response = await httpClient.SendAsync(request, cts.Token);
return response;
}
我读过一个类似的问题here,但我的 gui 线程没有做太多。我读过here 我可能用完了线程。是这个问题吗,我该如何解决? 我知道它是 Send Async,因为如果我用下面的简单任务替换代码,就不会阻塞。
await Task.Run(() =>
{
Thread.Sleep(1000);
});
【问题讨论】:
-
我知道发生了什么。您有 500 多个 Http 请求一次都抛出超时异常......当它被锁定时,请注意您的“输出”窗口。
-
我认为 OP 意味着在 UI 线程上完成了一些工作,并且它中断了 gif 的流畅动画。是的,因为您正在使用 async 并等待它实际上并不意味着线程,并且延续将在 UI 上下文中运行。如果您想确保一切都与 ui 完全隔离,我建议卸载。 Task.Run(一切)
-
是的,我确实有超时异常,我尝试在 Send Async 周围捕获,但它们不应该在自己的线程上安全处理吗? @JoePhillips 阻塞的意思,加载微调器 gif 卡住了,我也无法点击任何 ui 按钮。
-
我在说什么:它被锁定了,因为你处于调试模式并且调试器试图一次说“嘿,你有一个异常”500 次。在 Release 模式下运行它,看看它是否仍然锁定。另外,你做错了超时。
-
@Andy ,是的,有效。 gif 不是很流畅,但要好得多,我很高兴接受这个作为答案。您的意思是取消令牌的设置有误吗?
标签: c# multithreading asynchronous async-await dotnet-httpclient