[英]Prevent winforms UI block when using async/await
I'm fairly new to async/await programming and sometimes I feel that I understand it, and then all of a sudden something happens and throws me for a loop. 我对async / await编程很新,有时候我觉得我理解它,然后突然发生了一些事情,并引发了我的循环。
I'm trying this out in a test winforms app and here is one version of a snippet that I have. 我在测试winforms应用程序中尝试这个,这是我的一个版本的片段。 Doing it this way will block the UI
这样做会阻止UI
private async void button1_Click(object sender, EventArgs e)
{
int d = await DoStuffAsync(c);
Console.WriteLine(d);
}
private async Task<int> DoStuffAsync(CancellationTokenSource c)
{
int ret = 0;
// I wanted to simulator a long running process this way
// instead of doing Task.Delay
for (int i = 0; i < 500000000; i++)
{
ret += i;
if (i % 100000 == 0)
Console.WriteLine(i);
if (c.IsCancellationRequested)
{
return ret;
}
}
return ret;
}
Now, when I make a slight change by wrapping the body of "DoStuffAsync()" in a Task.Run it works perfectly fine 现在,当我通过在Task.Run中包装“DoStuffAsync()”的主体进行轻微更改时,它的工作完全正常
private async Task<int> DoStuffAsync(CancellationTokenSource c)
{
var t = await Task.Run<int>(() =>
{
int ret = 0;
for (int i = 0; i < 500000000; i++)
{
ret += i;
if (i % 100000 == 0)
Console.WriteLine(i);
if (c.IsCancellationRequested)
{
return ret;
}
}
return ret;
});
return t;
}
With all that said, what is the proper way to handle this scenario? 尽管如此,处理这种情况的正确方法是什么?
When you write such code: 当你写这样的代码时:
private async Task<int> DoStuffAsync()
{
return 0;
}
This way you are doing things synchronously, because you are not using await
expression. 这样你就可以同步处理,因为你没有使用
await
表达式。
Pay attention to the warning: 注意警告:
This async method lacks 'await' operators and will run synchronously.
这种异步方法缺少“等待”运算符并将同步运行。 Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
考虑使用'await'运算符等待非阻塞API调用,或'await Task.Run(...)'在后台线程上执行CPU绑定工作。
Based on the warning suggestion you can correct it this way: 根据警告建议,您可以这样纠正:
private async Task<int> DoStuffAsync()
{
return await Task.Run<int>(() =>
{
return 0;
});
}
To learn more about async/await you can take a look at: 要了解有关async / await的更多信息,您可以查看:
You just need to change the DoStuffAsync task little bit, as below. 您只需稍微更改DoStuffAsync任务,如下所示。
private async Task<int> DoStuffAsync(CancellationTokenSource c)
{
return Task<int>.Run(()=> {
int ret = 0;
// I wanted to simulator a long running process this way
// instead of doing Task.Delay
for (int i = 0; i < 500000000; i++)
{
ret += i;
if (i % 100000 == 0)
Console.WriteLine(i);
if (c.IsCancellationRequested)
{
return ret;
}
}
return ret;
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.