我想问你关于正确架构何时使用的意见Task.Run.我在WPF .NET 4.5应用程序(使用Caliburn Micro框架)中遇到了滞后的UI.
基本上我在做(非常简化的代码片段):
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();
}
}
Run Code Online (Sandbox Code Playgroud)
从我阅读/看到的文章/视频中,我知道await async不一定在后台线程上运行,并且需要在后台开始工作,需要等待它Task.Run(async () => …
异步方法在调用者上下文/线程上运行同步,直到其执行路径遇到 I/O 或涉及一些等待的类似任务,然后它不等待,而是返回到原始调用者,稍后恢复其继续。问题是,实现“等待”方法的首选方式是什么。文件/网络/等异步方法是如何做到的?
假设我有一个方法,其中涉及一些等待,当前开箱即用的 IO 未涵盖这些等待。我不想阻止调用线程,也不想强迫我的调用者执行 a 来Task.Run()卸载我,我想要一个干净的异步/等待模式,以便我的调用者可以无缝集成我的库,并且我可以在其上下文上运行,直到这样我需要屈服的时候了。为了便于论证,让我们假设我想要创建一个未涵盖的新 IO 库,并且我需要一种方法来使所有保持异步的粘合在一起。
我Task.Yield还要继续吗?我必须自己做Task.Run/Task.Wait等吗?两者看起来更像是相同的抽象(这带来了如何收益的问题Yield)。我很好奇,因为有很多关于 async/await 延续如何为消费者工作以及所有 IO 库如何准备就绪的讨论,但很少有人谈论实际的“突破”点如何工作以及流程制造商应如何实现它。同步路径末尾的代码如何实际释放控制以及该方法在该点和之后如何运行。