如果使用库,则使用Task.Run的位置不支持async await

时间:2017-08-11 01:01:08

标签: c# performance asynchronous async-await

我有一个通过网络发送消息的应用程序,我想在等待消息发送和响应时执行其他工作。我通过调用“await SendMessageAsync”来启动消息传递过程,该过程具有以下职责:

public async Task<bool> SendMessageAsync()
{
    //Do Some Work
    //Send First Message
    //More Work
    //Send Second Message
    //More Work
    //Send Third Message
}

如果我的第三方库支持它,我会这样写:

public async Task<bool> SendMessageAsync()
{
     //Do Some Work
     await LibrarySendMessageAsync(firstMessage);
     //More Work
     await LibrarySendMessageAsync(secondMessage);
     //More Work
     await LibrarySendMessageAsync(thirdMessage);
}

但是SendMessageAsync在超时时无法正常工作。所以我需要介绍一些并行性并使用Task.Run。

我的问题是:在Task.Run中包装整个上面的方法,或者将每个SendMessage方法包装在自己的Task.Run中会不会更好?

public async Task<bool> SendMessageAsync()
{
     //Do Some Work
     await Task.Run(() => LibrarySendMessage(firstMessage));
     //More Work
     await Task.Run(() => LibrarySendMessage(secondMessage));
     //More Work
     await Task.Run(() => LibrarySendMessage(thirdMessage));
}

VS

public async Task<bool> SendMessageAsync()
{
    await Task.Run(() => 
    {
    //Do Some Work
    LibrarySendMessage(firstMessage);
    //More Work
    LibrarySendMessage(secondMessage);
    //More Work
    LibrarySendMessage(thirdMessage);
    });
}

性能(速度)对于此应用程序非常重要。将以高频率重复调用SendMessageAsync。

2 个答案:

答案 0 :(得分:2)

这取决于。 将整个事物包装在一个Task.run中在逻辑上更容易理解。创建任务后,将同步发送三条消息。同步代码总是更容易编写,读取和调试

在性能方面更复杂。在这两种情况下,3条消息都按顺序发送。

三个Task.Runs消耗更少的线程(线程更快地返回到池中)但是会创建更多任务以及承担从一个任务转换到另一个任务的成本。单个任务将导致线程阻塞更长时间。您将需要线程池中的更多线程来处理相同数量的消息。您将平衡唤醒线程的成本以继续执行并从队列中选择任务以继续执行。

余额将取决于发送3条消息需要多长时间,您可以承受多少线程池线程,预期通过的内容,甚至消息到达的模式(均匀与零星)。当然,最终一切都取决于分析。

答案 1 :(得分:2)

基本上你的第二个选择......你有一个方法: -

.aggregate()

基本上不应该是异步的。你基本上说你希望方法是同步的......所以写下那个方法

 public async Task<bool> SendMessageAsync()

不要将同步代码写成奇怪的混淆异步方法。那么如果你想在一个线程中做那个工作,那么等待......

public bool SendMessage()
{
    //Do Some Work
    LibrarySendMessage(firstMessage);
    //More Work
    LibrarySendMessage(secondMessage);
    //More Work
    LibrarySendMessage(thirdMessage);
}

您可以将其包装到原始方法await Task.Run(() => SendMessage());