在Task.Run中包装IO绑定的异步方法

时间:2019-04-28 12:01:24

标签: c# asynchronous async-await

以下引用自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绑定操作完成就产生另一个线程”

似乎上面的代码和我从他人那里读到的概念是矛盾的。你能告诉我哪个是正确的吗?

1 个答案:

答案 0 :(得分:1)

值得注意的是,Task.Run在实际的SynchronizationContext调用之内会放下用户界面的Run()。您可以完全摆脱全局Task.Run,而只需await Firstawait Second,然后Task.RunMashup部分(如果我们假设该方法是 受CPU约束的),但细微的区别是,您将在每次等待之间往返UI线程的Dispatcher(假设它们是异步完成的,考虑到这是下载操作,他们很可能会这样做) )。

因此,换句话说,这里的Task.Run可以节省UI线程免于不必要的跳转。在这个过度简化的示例中,这可以说是完全可以忽略不计的,但是在实际场景中要牢记这一点。您不希望您的宝贵UI线程不断进行异步簿记操作,尽管它们可能是短暂的。通用工作者线程池非常适合每秒进行数百万个线程切换,因此您的UI线程只能将时间花在实际的UI事情上。