1

我有一台 1 核机器,我想使用 async 和 await 来提高我的代码性能。代码有两个主要部分。第一个IO操作。(从 azure 服务总线队列中读取多个 sessionId),第二个,处理数据 - CPU 很重。我将 DequeueAsync 方法包装在一个返回任务的异步方法中:

private async Task<SomeReturnValue> AcceptFromQueueAsync(){
  try{ 
       SomeReturnValue result = await DequeueAsync.configureAwait(false);
       return SomeReturnValue;  
  }
  catch{
   //logging and stuff
  }

CPU 重的方法是 sync: DoSyncWork() 由于第二部分是 CPU 重的我不想使用并行(实际上不能...) CPU 部分只能在 IO 部分完成时启动。鉴于以上是以下实现与 1 个 cpu 机器一起使用的方法吗?

private void AcceptAndProcessWrapper(){
    //Count is some cosnt defined outside the method
    _acceptTasks = new List<Task<SomeReturnValue>>();
     for (var i = 0; i < Count; i++)
     {
                    _acceptTasks.Add(AcceptFromQueueAsync());
      }
      //The use of list is for convince in processing  
      Task.WaitAll(_acceptTasks.ToArray());
      //The CPU part 
       Task.Run(DoSyncWork).Wait();
 }

我知道我不能将 Task.Run() 用于同步部分,但我想允许在多个内核上实现功能(通过使用 Task.Run() 启动多个任务并将它们保存在一个数组中)以上实现. (多次调用返回任务的异步方法)提高性能?或者我应该为每个异步调用启动一个新任务,例如 Task.Run(AcceptFromQueueAsync)?

4

4 回答 4

3

您拥有的代码确实会并行执行异步出队。它将立即启动所有异步任务,然后等到它们全部完成后再继续。

添加额外的呼叫Task.Run将无济于事。在另一个线程中启动异步任务只是增加了额外的开销而没有任何附加值。 Task.Run应该用于在另一个线程中运行CPU 密集型工作,而不是在另一个线程中运行异步工作。

于 2013-11-12T18:10:16.253 回答
1

说到 Task(s) 的性能(如果您将来使用它DoSyncWork),您还应该记住Task.Run默认情况下使用 ThreadPool,但是 Thread 池中的线程被期望做一些快速而小的工作。如果任务确实是一些“繁重”的任务,您应该考虑在新创建的线程中运行它们,这也可能会强制执行以下操作:

new Task(() => { }, TaskCreationOptions.LongRunning);

编辑:

在下面的一些谈话之后,我想把这些东西弄清楚一点。

目前,Task.Run(DoSyncWork).Wait();真的没有任何意义(甚至可能需要额外的时间在另一个线程上运行任务(甚至来自 ThreadPool 的),但是如果您将来想使用多个内核,您显然应该将该任务移至另一个要运行的线程(如果它确实占用大量 CPU,则考虑将任务作为“ LongRunning ”运行)(如果您的应用程序当然需要它(不确定您拥有的应用程序类型))。在这种情况下,有仍然不需要.Wait()立即打电话给那里。

于 2013-11-12T18:14:27.487 回答
0

异步运行第一部分可能有意义,取决于它的名称中包含 Async ,这表明它无论如何都不会阻塞,在这种情况下不需要,但绝对不需要异步运行 DoSyncWork 因为它只有一个进程,你正在等待它完成。

于 2013-11-12T18:09:50.110 回答
0

我使用与此类似的模式来尝试尽可能多地保持 IO 和 CPU 运行

public async void DoWork()
{
    Task cpuBoundTask = null;
    Task ioBoundTask = null;

    while(true)
    {
         ioBoundTask = DoIOBoundStuff();
         var ioResult = await ioBoundTask;

         if(cpuBoundTask != null)
         {
             await cpuBoundTask;
         }
         cpuBoundTask = DoCpuBoundStuff(ioResult);
    }
 }
于 2013-11-12T20:33:07.937 回答