gpt4 book ai didi

c# - 何时正确使用 Task.Run 以及何时使用 async-await

转载 作者:IT王子 更新时间:2023-10-29 03:28:31 24 4
gpt4 key购买 nike

我想请教您对何时使用 Task.Run 的正确架构的看法。我在 WPF .NET 4.5 中遇到滞后的 UI应用程序(使用 Caliburn Micro 框架)。

基本上我在做(非常简化的代码片段):

public class PageViewModel : IHandle<SomeMessage>
{
...

public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();

// Makes UI very laggy, but still not dead
await this.contentLoader.LoadContentAsync();

HideLoadingAnimation();
}
}

public class ContentLoader
{
public async Task LoadContentAsync()
{
await DoCpuBoundWorkAsync();
await DoIoBoundWorkAsync();
await DoCpuBoundWorkAsync();

// I am not really sure what all I can consider as CPU bound as slowing down the UI
await DoSomeOtherWorkAsync();
}
}

从我阅读/看到的文章/视频中,我知道 await async 不一定在后台线程上运行,要在后台开始工作,您需要用 await Task.Run(async () => ... ) 包装它。使用 async await 不会阻塞 UI,但它仍然在 UI 线程上运行,因此会导致延迟。

Task.Run 放在哪里最好?

我是不是应该

  1. 包装外部调用,因为这对 .NET 来说是较少的线程工作

  2. ,或者我应该只使用 Task.Run 包装内部运行的 CPU 绑定(bind)方法,因为这使得它可以在其他地方重用?我不确定在核心深处开始处理后台线程是否是个好主意。

广告(1),第一个解决方案是这样的:

public async void Handle(SomeMessage message)
{
ShowLoadingAnimation();
await Task.Run(async () => await this.contentLoader.LoadContentAsync());
HideLoadingAnimation();
}

// Other methods do not use Task.Run as everything regardless
// if I/O or CPU bound would now run in the background.

广告(2),第二种解决方案是这样的:

public async Task DoCpuBoundWorkAsync()
{
await Task.Run(() => {
// Do lot of work here
});
}

public async Task DoSomeOtherWorkAsync(
{
// I am not sure how to handle this methods -
// probably need to test one by one, if it is slowing down UI
}

最佳答案

注意 guidelines for performing work on a UI thread ,收集在我的博客上:

  • 一次阻塞界面线程的时间不要超过 50 毫秒。
  • 您每秒可以在 UI 线程上安排约 100 个延续; 1000 太多了。

您应该使用两种技术:

1) 尽可能使用 ConfigureAwait(false)

例如,await MyAsync().ConfigureAwait(false); 而不是 await MyAsync();

ConfigureAwait(false) 告诉 await 您不需要在当前上下文中恢复(在这种情况下,“在当前上下文中”意味着“在界面线程”)。但是,对于该 async 方法的其余部分(在 ConfigureAwait 之后),您无法执行任何假设您处于当前上下文中的操作(例如,更新 UI 元素)。

有关详细信息,请参阅我的 MSDN 文章 Best Practices in Asynchronous Programming .

2) 使用 Task.Run 调用 CPU 绑定(bind)方法。

您应该使用 Task.Run,但不要在您希望可重用的任何代码(即库代码)中使用。因此,您使用 Task.Run调用方法,而不是作为方法的实现的一部分。

所以纯粹的 CPU 绑定(bind)工作看起来像这样:

// Documentation: This method is CPU-bound.
void DoWork();

您将使用 Task.Run 调用:

await Task.Run(() => DoWork());

混合 CPU 绑定(bind)和 I/O 绑定(bind)的方法应该有一个 Async 签名,并在文档中指出它们的 CPU 绑定(bind)性质:

// Documentation: This method is CPU-bound.
Task DoWorkAsync();

您还可以使用 Task.Run 调用它(因为它部分受 CPU 限制):

await Task.Run(() => DoWorkAsync());

关于c# - 何时正确使用 Task.Run 以及何时使用 async-await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18013523/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com