C# 异步方法不能异步运行
我正在用WPF编写下面的代码。但是,它不会异步运行。我已经注释了代码被阻塞的那一行。请让我知道我在哪里犯错C# 异步方法不能异步运行,c#,async-await,task-parallel-library,C#,Async Await,Task Parallel Library,我正在用WPF编写下面的代码。但是,它不会异步运行。我已经注释了代码被阻塞的那一行。请让我知道我在哪里犯错 private async void txtSamplerRequest\u单击(对象发送方,RoutedEventArgs e) { 等待下载数据(); } 异步任务下载数据() { 字符串授权=txtAuthentication.Text; 字符串cookie=txtCookie.Text; 尝试 { var vvv=可枚举范围(0,50); List TaskList=新列表();
private async void txtSamplerRequest\u单击(对象发送方,RoutedEventArgs e)
{
等待下载数据();
}
异步任务下载数据()
{
字符串授权=txtAuthentication.Text;
字符串cookie=txtCookie.Text;
尝试
{
var vvv=可枚举范围(0,50);
List TaskList=新列表();
foreach(在vvv中的int s)
{
Task LastTask=ZerodhaOperations.MyHttpRequest(“,authorization,cookie,“5minute”);//即使这个方法是异步方法,我也添加了dummy Task.Delay(1)来异步运行这个方法。下面是这个类的完整定义。
任务列表。添加(上一个任务);
}
wait Task.WhenAll(TaskList);//是指它在异步产生时捕获一个“上下文”。详细信息在链接中,但在本例中,异步方法在WPF UI线程上运行,因此它捕获一个将在该UI线程上恢复运行的上下文
因此,等待任务。延迟(1)
实际上是在强迫MyHttpRequest
异步运行,但接下来发生的事情会让你大吃一惊。MyHttpRequest
是否等待
,它捕获UI上下文并返回一个不完整的任务。这会在下载数据
中多次发生,它收集不完整的任务,然后wait
s任务。当所有任务都执行时。因此DownloadData
返回一个未完成的任务,该任务被事件处理程序wait
调用,事件处理程序将控制权返回给WPF消息循环
现在,接下来发生的事情是那些Task.Delay
计时器几乎立即启动。因此,MyHttpRequest
恢复其async
方法,并且由于其wait
捕获了该UI上下文,它恢复在UI线程上运行。因此wait Task.Delay(1)
确实导致了WPF消息循环的屈服,但实际上,UI线程接下来要做的就是恢复那些异步
方法
其余的async
方法是同步的,阻塞了UI线程
因此,要解决这个问题,您可以使这些方法真正异步。完全删除等待任务。延迟(1)
,用异步API替换同步API(GetResponseAsync
,ReadToEndAsync
)。或者,如果要进一步更新代码,请将WebRequest
替换为HttpClient
另一个选项是保持代码同步,只需使用任务。运行
在后台线程上运行同步代码。同样,您将删除等待任务。延迟(1)
,这次您将更改方法签名为同步。然后您可以将调用包装为(同步)MyHttpRequest
在Task.Run
中,例如Task LastTask=Task.Run(()=>ZerodhaOperations.MyHttpRequest(“,授权,cookie,“5分钟”))
Task.Run
解决方案不如异步解决方案理想,但是如果您还有很多其他代码需要同步,那么它是可以接受的
请注意,无论哪种方式,Task.Delay(1)
的使用都是错误的。它不会“异步运行[the]方法”。异步运行方法的正确方式是让它调用异步API,而不是调用阻塞API。您不会使用异步代码的好处。Task.Delay(1)
很快就会注意到,在代码同步之后。使任务延迟(5000)
查看UI在5秒钟内没有被阻止。但是在那之后,任务。延迟
您的代码是同步的,并且会阻止UI。相反,使用异步方法从web服务检索数据。鼓轮滚动…您的HttpRequest是同步的!我已经很久没有使用WebRequest
了,但是如果它们有async
方法的话但是,您应该真正使用IHttpClientFactory
并完成it@MichałTurczyn-async void
对于UI控件,事件处理程序完全可以使用,异常将正确抛出。但是您当然应该切换到HttpClient并使用其异步方法。