运行两个并行异步任务,并收集在.NET 4.5结果(Run two async tasks in p

2019-06-18 02:26发布

我一直在努力了一段时间才能得到的东西我想与.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;
}

非工作代码:

更新:这实际上可行,是做了正确的方式,唯一的问题是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;
}

Answer 1:

您应该使用Task.Delay,而不是睡眠的异步编程,然后用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;
        }
    }


Answer 2:

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


Answer 3:

当你的Sleep方法是异步, Thread.Sleep是没有的。 异步的整体思路是重用一个线程,不要启动多个线程。 因为你已经使用同步调用了Thread.Sleep封锁,这不是去上班。

我假设Thread.Sleep是你真正想要做的简化。 您能否实际执行被编码为异步方法?

如果你确实需要运行多个同步阻塞调用,看看其他地方我想!



Answer 4:

要回答这个问题:

我想睡觉是一个异步方法,因此可以等待其他方法

你也许可以改写Sleep这样的功能:

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    var task = Task.Run(() => Thread.Sleep(ms));
    await task;
    Console.WriteLine("Sleeping for " + ms + "END");
    return ms;
}

static void Main(string[] args)
{
    Console.WriteLine("Starting");

    var task1 = Sleep(2000);
    var task2 = Sleep(1000);

    int totalSlept = task1.Result +task2.Result;

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

运行此代码将输出:

Starting
Sleeping for 2000
Sleeping for 1000
*(one second later)*
Sleeping for 1000END
*(one second later)*
Sleeping for 2000END
Slept for 3000 ms


Answer 5:

又到周末了!

    public async void Go()
    {
        Console.WriteLine("Start fosterage...");

        var t1 = Sleep(5000, "Kevin");
        var t2 = Sleep(3000, "Jerry");
        var result = await Task.WhenAll(t1, t2);

        Console.WriteLine($"My precious spare time last for only {result.Max()}ms");
        Console.WriteLine("Press any key and take same beer...");
        Console.ReadKey();
    }

    private static async Task<int> Sleep(int ms, string name)
    {
            Console.WriteLine($"{name} going to sleep for {ms}ms :)");
            await Task.Delay(ms);
            Console.WriteLine("${name} waked up after {ms}ms :(";
            return ms;
    }


Answer 6:

这篇文章帮助解释了很多事情。 它在FAQ风格。

异步/等待FAQ

这部分解释了为什么Thread.Sleep同原来的线程上运行-导致我最初的混乱。

请问“异步”关键字导致的方法调用排队到线程池? 要创建一个新的线程? 要启动火箭飞船到火星?

编号编号而且没有。 请参阅前面的问题。 的“异步”关键字指示给“伺机”可以被本方法的内部使用,使得该方法可以在一个点AWAIT挂起和具有等待实例完成时其执行异步恢复编译器。 这就是为什么如果没有“等待”标记为“异步”的方法中,编译器会发出警告。



文章来源: Run two async tasks in parallel and collect results in .NET 4.5