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

问题描述 投票:0回答:1

以下引自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);
    });
}

Question

根据我从其他资源中读到的内容,IO绑定的异步方法不应该用Task.Run包装,因为“我们不需要生成另一个线程来等待IO绑定操作完成”。

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

c# asynchronous async-await
1个回答
1
投票

值得注意的是,Task.Run在实际的SynchronizationContext通话中丢弃了你的UI的Run()。你可以很好地摆脱全球Task.Run,简单地await Firstawait Second,然后Task.Run只有Mashup部分(如果我们保持这种方法是CPU绑定的假设),但微妙的区别是你会做往返您的UI线程的Dispatcher在每个等待之间(假设它们是异步完成的,考虑到它是下载操作,它们很可能会这样做)。

换句话说,这里的Task.Run具有将UI线程从无用的跳转中保存的优点。在这个过度简化的示例中,这可以说完全可以忽略不计,但在现实场景中需要牢记这一点。你不希望你宝贵的UI线程不断地进行异步簿记操作,不管它们是多么短暂。通用工作线程池非常适合每秒执行数百万个线程切换,然后您的UI线程可以只花时间在实际的UI事物上。

© www.soinside.com 2019 - 2024. All rights reserved.