当正确使用Task.Run当刚刚异步的await [英] When correctly use Task.Run and when just async-await

查看:1300
本文介绍了当正确使用Task.Run当刚刚异步的await的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一下你对你的了解正确的体系结构时使用Task.Run意见。我遇到在我们的WPF .NET 4.5的应用程序laggy UI。 (与卡利微架构)。

I would like to ask you on your opinion about the correct architecture when to use Task.Run. I am experiencing laggy UI in our WPF .net 4.5 app. (with Caliburn Micro framework).

什么我基本上做的是(非常简化code段)

What I am basically doing is (very simplified code snippets)

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

   public async void Handle(SomeMessage message)
   {
      ShowLoadingAnimation();
      await this.contentLoader.LoadContentAsync();  // makes UI very laggy, but still not dead
      HideLoadingAnimation();   
   }
}

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

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

从文章/视频我看了/锯我知道,等待异步未在BG线程运行的必然,并开始在后台您需要的await 来包装它的工作Task.Run(异步() = GT; ...)。使用异步伺机不会阻止用户界面,但仍是在UI线程上运行,所以它使它laggy。

From the articles/videos I read/saw I know that await async is not necessarily running on bg thread and to start work in background you need to wrap it with await Task.Run(async () => ... ). Using async await does not block UI, but still is running on the UI thread, so it is making it laggy.

我的问题是在哪里是把Task.Run的最佳场所。

我应该只是
      (1)包装的外呼叫,因为这是为达少穿线工作
   或者我应该
      (2)只换CPU绑定方法与Task.Run内部运行,因为这使得它可重复使用其他地方吗?我不知道在这里如果深核心BG线程开始工作是一个好主意。

Should I just (1) wrap the outer call because this is less threading work for .net or should I (2) wrap only CPU bound methods internally running with Task.Run as this makes it reusable for other places? I am not sure here if starting work on bg threads deep in core is a good idea.

(1)拳头解决方案将看到这样

(1) fist solution would see like this

   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 IO or CPU bound would now run in background

(2)第二个解决方案会看到这样

(2) second solution would see like this

   public async Task DoCpuBoundWorkAsync()
   {
        await Task.Run(() => {
          ...
          do lot of stuff here
          ...
          });
   }

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

我希望这是有道理的。 THX的提前你的意见。

I hope this makes sense. Thx for your opinions in advance.

推荐答案

注意指南对UI线程演艺工作,收集了我的博客:

Note the guidelines for performing work on a UI thread, collected on my blog:


  • 请不要在同一时间阻止50ms以上的UI线程。

  • 您可以安排每秒UI线程〜100延续; 1000是太多了。

有两种方法,你应该使用:

There are two techniques you should use:

1)使用 ConfigureAwait(假)时即可。

1) Use ConfigureAwait(false) when you can.

例如,等待MyAsync()ConfigureAwait(假); 而不是等待MyAsync();

ConfigureAwait(假)通知等待,你不需要恢复当前上下文(在此的情况下,在目前的情况下,UI线程的意思)。然而,对于异步法的其余部分(后 ConfigureAwait ),你不能做任何假设你在目前情况下(例如,更新UI元素)。

ConfigureAwait(false) tells the await that you do not need to resume on the current context (in this case, "on the current context" means "on the UI thread"). However, for the rest of that async method (after the ConfigureAwait), you cannot do anything that assumes you're in the current context (e.g., update UI elements).

有关详细信息,请参阅我的MSDN文章最佳实践异步编程

For more information, see my MSDN article Best Practices in Asynchronous Programming.

2)使用 Task.Run 来调用CPU绑定的方法。

2) Use Task.Run to call CPU-bound methods.

您应该使用 Task.Run ,但不是你想被重用任何code(即库code)内。所以你用 Task.Run 来的呼叫的方法,而不是作为一部分的实施方法

You should use Task.Run, but not within any code you want to be reusable (i.e., library code). So you use Task.Run to call the method, not as part of the implementation of the method.

所以,纯粹的CPU密集型的工作是这样的:

So purely CPU-bound work would look like this:

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

,你会打电话使用 Task.Run

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

中的方法是的混合的的CPU绑定和I / O密集​​型应该有文件指出他们的CPU-一个异步签名结合性质:

Methods that are a mixture of CPU-bound and I/O-bound should have an Async signature with documentation pointing out their CPU-bound nature:

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

你会也呼吁使用 Task.Run (因为它是部分CPU绑定):

Which you would also call using Task.Run (since it is partially CPU-bound):

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

这篇关于当正确使用Task.Run当刚刚异步的await的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆