以下引用自Using the Built-in Task-based Combinators部分。
public async void button1_Click(object sender, EventArgs e)
{
pictureBox1.Image = await Task.Run(async() =>
{
using(Bitmap bmp1 = await DownloadFirstImageAsync())
using(Bitmap bmp2 = await DownloadSecondImageAsync())
return Mashup(bmp1, bmp2);
});
}
根据我从其他资源中所读到的内容,IO绑定的异步方法不应用Task.Run
包装,因为“我们不需要等待IO绑定操作完成就产生另一个线程”
似乎上面的代码和我从他人那里读到的概念是矛盾的。你能告诉我哪个是正确的吗?
答案 0 :(得分:1)
值得注意的是,Task.Run
在实际的SynchronizationContext
调用之内会放下用户界面的Run()
。您可以完全摆脱全局Task.Run
,而只需await First
,await Second
,然后Task.Run
仅Mashup
部分(如果我们假设该方法是 受CPU约束的),但细微的区别是,您将在每次等待之间往返UI线程的Dispatcher(假设它们是异步完成的,考虑到这是下载操作,他们很可能会这样做) )。
因此,换句话说,这里的Task.Run
可以节省UI线程免于不必要的跳转。在这个过度简化的示例中,这可以说是完全可以忽略不计的,但是在实际场景中要牢记这一点。您不希望您的宝贵UI线程不断进行异步簿记操作,尽管它们可能是短暂的。通用工作者线程池非常适合每秒进行数百万个线程切换,因此您的UI线程只能将时间花在实际的UI事情上。