并行运行两个异步任务并在.NET 4.5中收集结果

Sim*_*ver 109 c# asynchronous task-parallel-library .net-4.5

我已经尝试了一段时间来获得一些我认为可以简单地使用.NET 4.5的东西

我想同时启动两个长时间运行的任务,并
以最佳的C#4.5(RTM)方式收集结果

以下作品,但我不喜欢它,因为:

  • 我想Sleep成为一个异步方法,所以它可以是await其他方法
  • 它看起来很笨拙 Task.Run()
  • 我认为这甚至根本不使用任何新的语言功能!

工作代码:

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Task.Run(() => Sleep(5000));    
    var task2 = Task.Run(() => Sleep(3000));

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}

private static int Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    Console.WriteLine("Sleeping for " + ms + " FINISHED");
    return ms;
}
Run Code Online (Sandbox Code Playgroud)

非工作代码:

更新:这实际上是有效的,并且是正确的方法,唯一的问题是 Thread.Sleep

此代码不起作用,因为调用Sleep(5000)立即启动任务运行,因此Sleep(1000)在完成之前不会运行.这是真的,即使Sleepasync,我不是太快使用await或打电话.Result.

我想也许有一种方法可以Task<T>通过调用方法来获得非运行,async这样我就可以调用Start()这两个任务,但我无法弄清楚如何Task<T>通过调用异步方法来获取.

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Sleep(5000);    // blocks
    var task2 = Sleep(1000);

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
}

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    return ms;
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*art 106

async Task<int> LongTask1() { 
  ...
  return 0; 
}

async Task<int> LongTask2() { 
  ...
  return 1; 
}

...
{
   Task<int> t1 = LongTask1();
   Task<int> t2 = LongTask2();
   await Task.WhenAll(t1,t2);
   //now we have t1.Result and t2.Result
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信这个解决方案要求Go方法也是异步的,这意味着它暴露了异步的能力.如果你想要更像askers的情况,其中调用者的'Go`方法是同步的,但想要异步完成两个独立的任务(即既不需要在另一个之前完成,但两者都必须在执行继续之前完成)那么**`任务.WaitAll`**会更好,你不需要await关键字,因此不需要调用`Go`方法本身就是异步.**两种方法都不是更好,只是你的目标是什么.** (10认同)
  • 我+1 因为你将t1,t2 声明为Task,这是正确的方法。 (4认同)

sof*_*eda 74

您应该使用Task.Delay而不是Sleep进行异步编程,然后使用Task.WhenAll组合任务结果.任务将并行运行.

public class Program
    {
        static void Main(string[] args)
        {
            Go();
        }
        public static void Go()
        {
            GoAsync();
            Console.ReadLine();
        }
        public static async void GoAsync()
        {

            Console.WriteLine("Starting");

            var task1 = Sleep(5000);
            var task2 = Sleep(3000);

            int[] result = await Task.WhenAll(task1, task2);

            Console.WriteLine("Slept for a total of " + result.Sum() + " ms");

        }

        private async static Task<int> Sleep(int ms)
        {
            Console.WriteLine("Sleeping for {0} at {1}", ms, Environment.TickCount);
            await Task.Delay(ms);
            Console.WriteLine("Sleeping for {0} finished at {1}", ms, Environment.TickCount);
            return ms;
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案...但我认为这是错误的答案,直到我运行它.然后我明白了.它确实在5秒内执行.诀窍是不要立即等待任务,而是等待Task.WhenAll. (8认同)