c# - 异步执行一组任务时,它不应该与运行时间最长的任务一样长吗?

标签 c# multithreading asynchronous task

我有一个包含 10 个任务的列表,每个任务需要 15 秒。所有任务都在一个数组中并异步执行。整个场景不应该花 15 秒左右吗?从下面的代码中,请注意在输出中整个集合需要 21 秒。当我将其更改为 100 个任务时,需要一分钟多的时间。就好像创建任务只需要一秒钟。我错过了什么?谢谢!

static void Main(string[] args)
{
    var mainStart = DateTime.Now;
    var tasks = new List<Task>();
    for (int i = 0; i < 10; i++)
    {
        tasks.Add(Task.Factory.StartNew((Object data) =>
        {
            var index = (int)data;
            var stepStart = DateTime.Now;
            Console.WriteLine("{0} Starting {1} on thread {2}...", stepStart, index, Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(15000);
            var stepFinish = DateTime.Now;
            Console.WriteLine("{0} Finished {1} on thread {2}, duration: {3}",
                stepStart, index, Thread.CurrentThread.ManagedThreadId, stepFinish - stepStart);
        },
        i));
    }
    Task.WaitAll(tasks.ToArray());
    var mainFinish = DateTime.Now;
    Console.WriteLine("{0} Finished, duration {1}", DateTime.Now, mainFinish - mainStart);
    Console.WriteLine("Press any key to exit.");
    Console.Read();

    // Output
    //5/25/2017 8:03:43 PM Starting 0 on thread 10...
    //5/25/2017 8:03:43 PM Starting 1 on thread 11...
    //5/25/2017 8:03:43 PM Starting 2 on thread 12...
    //5/25/2017 8:03:43 PM Starting 3 on thread 13...
    //5/25/2017 8:03:44 PM Starting 4 on thread 14...
    //5/25/2017 8:03:45 PM Starting 5 on thread 15...
    //5/25/2017 8:03:46 PM Starting 6 on thread 16...
    //5/25/2017 8:03:47 PM Starting 7 on thread 17...
    //5/25/2017 8:03:48 PM Starting 8 on thread 18...
    //5/25/2017 8:03:49 PM Starting 9 on thread 19...
    //5/25/2017 8:03:43 PM Finished 0 on thread 10, duration: 00:00:15.0018957
    //5/25/2017 8:03:43 PM Finished 1 on thread 11, duration: 00:00:15.0175209
    //5/25/2017 8:03:43 PM Finished 2 on thread 12, duration: 00:00:15.0175209
    //5/25/2017 8:03:43 PM Finished 3 on thread 13, duration: 00:00:15.0165291
    //5/25/2017 8:03:44 PM Finished 4 on thread 14, duration: 00:00:15.0156567
    //5/25/2017 8:03:45 PM Finished 5 on thread 15, duration: 00:00:15.0156012
    //5/25/2017 8:03:46 PM Finished 6 on thread 16, duration: 00:00:15.0155997
    //5/25/2017 8:03:47 PM Finished 7 on thread 17, duration: 00:00:15.0155989
    //5/25/2017 8:03:48 PM Finished 8 on thread 18, duration: 00:00:15.0155985
    //5/25/2017 8:03:49 PM Finished 9 on thread 19, duration: 00:00:15.0156328
    //5/25/2017 8:04:04 PM Finished, duration 00:00:21.0322775
    //Press any key to exit.
}

最佳答案

名义上,异步工作允许其他事情在他们等待某事时继续进行......他们这样做的方式是等待耗时的东西(这通常是某种 I/O ).为了看到它的实际效果,您可以真正以异步方式运行该工作。例如:

static void Main( string[ ] args )
{
  var totalTime = DoSomeAsyncTasks( ).GetAwaiter( ).GetResult( );
  Console.WriteLine( "{0} Finished, duration {1}", DateTime.Now, totalTime );
  Console.WriteLine( "Press any key to exit." );
  Console.Read( );
}

async static Task<TimeSpan> DoSomeAsyncTasks( )
{
  var mainStart = DateTime.Now;
  var tasks = new List<Task>( );
  for ( int i = 0; i < 10; i++ )
  {
    var id = i;
    tasks.Add( DoATask( id ) );
  }
  await Task.WhenAll( tasks );
  var mainFinish = DateTime.Now;
  return mainFinish - mainStart;
}

static async Task DoATask( int stepId )
{
  var stepStart = DateTime.Now;

  Console.WriteLine(
    "{0} Starting {1} on thread {2}...",
    stepStart, stepId, Thread.CurrentThread.ManagedThreadId );

  //--> more accurately model waiting for I/O...
  await Task.Delay( TimeSpan.FromSeconds( 15 ) );

  var stepFinish = DateTime.Now;
  Console.WriteLine( "{0} Finished {1} on thread {2}, duration: {3}",
      stepStart, stepId, Thread.CurrentThread.ManagedThreadId, stepFinish - stepStart );
}

...返回:

5/25/2017 11:24:36 PM Starting 0 on thread 9...
5/25/2017 11:24:36 PM Starting 1 on thread 9...
5/25/2017 11:24:36 PM Starting 2 on thread 9...
5/25/2017 11:24:36 PM Starting 3 on thread 9...
5/25/2017 11:24:36 PM Starting 4 on thread 9...
5/25/2017 11:24:36 PM Starting 5 on thread 9...
5/25/2017 11:24:36 PM Starting 6 on thread 9...
5/25/2017 11:24:36 PM Starting 7 on thread 9...
5/25/2017 11:24:36 PM Starting 8 on thread 9...
5/25/2017 11:24:36 PM Starting 9 on thread 9...
5/25/2017 11:24:36 PM Finished 9 on thread 11, duration: 00:00:15.0085175
5/25/2017 11:24:36 PM Finished 8 on thread 12, duration: 00:00:15.0085175
5/25/2017 11:24:36 PM Finished 7 on thread 13, duration: 00:00:15.0315198
5/25/2017 11:24:36 PM Finished 6 on thread 14, duration: 00:00:15.0325121
5/25/2017 11:24:36 PM Finished 5 on thread 12, duration: 00:00:15.0335121
5/25/2017 11:24:36 PM Finished 3 on thread 11, duration: 00:00:15.0335121
5/25/2017 11:24:36 PM Finished 2 on thread 12, duration: 00:00:15.0355229
5/25/2017 11:24:36 PM Finished 1 on thread 11, duration: 00:00:15.0355229
5/25/2017 11:24:36 PM Finished 4 on thread 14, duration: 00:00:15.0335121
5/25/2017 11:24:36 PM Finished 0 on thread 13, duration: 00:00:15.0545213
5/25/2017 11:24:51 PM Finished, duration 00:00:15.0665191

(我做了所有与您的代码相同的事情 - 并且接受的答案确实......只是将其分散到方法中以使其更具说明性。)

从这里你应该看到,每个任务大约在同一时间开始,每个任务耗时大约 15 秒,但总运行时间也在 15 秒左右。这是因为,当一个任务在等待时,它让其他工作运行。另请注意,一切都在同一个单线程上运行。工作被等待交错。这非常酷 - 可能更符合您的预期。

关于c# - 异步执行一组任务时,它不应该与运行时间最长的任务一样长吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44191716/

相关文章:

c# - char 对象对应于哪个字符编码(Unicode 版本)集?

c# - 在 C# 中将 LDAP AccountExpires 转换为 DateTime

c# - 另一个C#死锁调试问题

javascript - 异步 - 回调不是函数

c# - 如何使用 lambda 表达式选择多列过滤器

multithreading - Send 只能为结构/枚举类型实现,不能为特征实现

java - 如何创建线程(素数和ArrayList)?

android - 使用协同程序读取和复制文件

jakarta-ee - 超时后的JavaEE 6 AsyncContext行为

c# - 使用 IronPython 和 .Net 的鼠标现状