Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何最好地并行运行两个异步任务,并等待两者的返回结果?_C#_Asynchronous_Async Await - Fatal编程技术网

C# 如何最好地并行运行两个异步任务,并等待两者的返回结果?

C# 如何最好地并行运行两个异步任务,并等待两者的返回结果?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我正在寻找一个简单的C#模式示例,它满足以下要求: 我想异步执行两个方法,在不等待第一个方法完成的情况下启动第二个方法 每个方法都接受一个参数并返回和输出值 然后我想在继续之前等待这两个结果 这似乎是一个我可以轻松使用async和Wait关键字的场景,但在看了几个Hello World示例后,我很惊讶我不能同时轻松满足上述所有标准。例如,虽然使用wait关键字使我的UI不被阻塞,并允许我的应用程序在我等待方法完成时继续响应事件,但这些方法仍在同步执行。或者,如果我能够异步执行,那么在尝试将输入参

我正在寻找一个简单的C#模式示例,它满足以下要求:

  • 我想异步执行两个方法,在不等待第一个方法完成的情况下启动第二个方法
  • 每个方法都接受一个参数并返回和输出值
  • 然后我想在继续之前等待这两个结果
  • 这似乎是一个我可以轻松使用async和Wait关键字的场景,但在看了几个Hello World示例后,我很惊讶我不能同时轻松满足上述所有标准。例如,虽然使用wait关键字使我的UI不被阻塞,并允许我的应用程序在我等待方法完成时继续响应事件,但这些方法仍在同步执行。或者,如果我能够异步执行,那么在尝试将输入参数传递给调用方法并返回结果时就会遇到问题

    以下内容似乎符合我的要求,并使我相信我能够充分利用它,但首先我想得到您关于如何改进它的反馈

    我以前玩过线程,发现这会使我的代码变得更复杂,并希望“async and await”关键字会使我的生活更轻松,但下面的代码似乎满足了我的要求,甚至没有使用这些关键字。我在这里使用“并行任务库”吗?如果是这样,您将如何将此库中的功能与异步和等待功能进行对比

    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ASyncCourse
    {
        static class Program
        {
            static void Main()
            {
                int result1 = 0;
                int result2 = 0;
    
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
    
                Task task1 = Task.Run(() => result1 = DoSomeWork(1));
                Debug.WriteLine($"After Task1: {stopWatch.Elapsed}");
    
                Task task2 = Task.Run(() => result2 = DoSomeOtherWork(10));
                Debug.WriteLine($"After Task2: {stopWatch.Elapsed}");
    
                Task.WaitAll(task1, task2);
                stopWatch.Stop();
    
                int sum;
                
                sum = result1 + result2; 
                Debug.WriteLine($"Sum: {sum}");
                Debug.WriteLine($"Final: {stopWatch.Elapsed}");
            }
    
            private static int DoSomeOtherWork(int waitFor)
            {
                Thread.Sleep(waitFor * 1000);
                return waitFor;
            }
    
            private static int DoSomeWork(int waitFor)
            {
                Thread.Sleep(waitFor * 1000);
                return waitFor;
            }
        }
    }
    
    您可以使用async和await模式以及
    await
    cpu绑定的任务,但是您需要使用
    async Task Main()
    入口点

    public static async Task Main()
    {
        var task1 = Task.Run(() => CpuWork1(1));
        var task2 = Task.Run(() => CpuWork2(10));
        
        var result1 = await task1;
        var result2 = await task2;
    
        // or
    
        var results = await Task.WhenAll(task1, task2) ;
    }
    
    如果您的工作负载IO绑定的,那么它们将具有
    异步任务
    签名,您只需
    等待
    方法返回的任务,与上面类似(并且不使用
    任务。运行

    完整示例

    static async Task Main()
    {
    
       var stopWatch = new Stopwatch();
       stopWatch.Start();
    
       var task1 = Task.Run(() =>  DoSomeWork(1));
       var task2 = Task.Run(() =>  DoSomeOtherWork(10));
    
       var results = await Task.WhenAll(task1, task2);
       stopWatch.Stop();
    
       Debug.WriteLine($"Sum: {results.Sum()}");
       Debug.WriteLine($"Final: {stopWatch.Elapsed}");
    }
    
    或者类似地使用异步方法

    static async Task Main()
    {
    
       var stopWatch = new Stopwatch();
       stopWatch.Start();
    
       var task1 = DoSomeWorkAsync(1);
       var task2 = DoSomeOtherWorkAsync(10);
    
       var results = await Task.WhenAll(task1, task2);
       stopWatch.Stop();
    
       Debug.WriteLine($"Sum: {results.Sum()}");
       Debug.WriteLine($"Final: {stopWatch.Elapsed}");
    }
    
    private static async Task<int> DoSomeOtherWorkAsync(int waitFor)
    {
       // some IO bound workload
       await Task.Delay(waitFor * 1000);
       return waitFor;
    }
    
    private static async Task<int> DoSomeWorkAsync(int waitFor)
    {
       // some IO bound workload
       await Task.Delay(waitFor * 1000);
       return waitFor;
    }
    
    static async Task Main()
    {
    var stopWatch=新秒表();
    秒表。开始();
    var task1=DoSomeWorkAsync(1);
    var task2=DoSomeOtherWorkAsync(10);
    var结果=等待任务.WhenAll(任务1,任务2);
    秒表;
    Debug.WriteLine($“Sum:{results.Sum()}”);
    Debug.WriteLine($“Final:{stopWatch.appeased}”);
    }
    专用静态异步任务DoSomeOtherWorkAsync(int waitFor)
    {
    //一些IO绑定的工作负载
    等待任务。延迟(等待*1000);
    返回等待;
    }
    专用静态异步任务DoSomeWorkAsync(int waitFor)
    {
    //一些IO绑定的工作负载
    等待任务。延迟(等待*1000);
    返回等待;
    }
    
    异步方法是一种旨在访问外部资源而不阻塞和浪费资源(额外线程)的方法

    使用
    Task.Delay(1000)
    模拟异步方法

    private async Task<int> LoadSomething(int value)
    {
        await Task.Delay(value * 1000);
        return value;
    }
    

    对所有方法使用
    async
    ,并让它们返回
    Task

    调用
    等待任务。延迟
    而不是
    线程。睡眠

    然后,您可以使用
    等待任务。whalll
    等待任务完成

    如果不将
    wait
    放在方法调用前面,则执行过程将继续进行,而不等待结果

    等待结果后,您可以调用
    Result
    ,以获取结果

    static async Task Main()
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
    
        Task<int> task1 = DoSomeWork(1);
        Console.WriteLine($"After Task1: {stopWatch.Elapsed}");
    
        Task<int> task2 = DoSomeOtherWork(10);
        Console.WriteLine($"After Task2: {stopWatch.Elapsed}");
    
        await Task.WhenAll(task1, task2);
        stopWatch.Stop();
    
        int sum = task1.Result + task2.Result;
        Console.WriteLine($"Sum: {sum}");
        Console.WriteLine($"Final: {stopWatch.Elapsed}");
    }
    
    private static async Task<int> DoSomeOtherWork(int waitFor)
    {
        await Task.Delay(waitFor * 1000);
        return waitFor;
    }
    
    private static async Task<int> DoSomeWork(int waitFor)
    {
        await Task.Delay(waitFor * 1000);
        return waitFor;
    }
    

    您可以使用wait关键字。异步操作并行执行。当我们需要等待直到得到结果时,使用wait before

    例如:

    var task1 = AsyncOperation1(2);
    var task2 = AsyncOperation1(5);
    
    
    var result1 = await task1;
    var result2 = await task2;
    

    使用最后两行而不是
    Task.WhenAll(task1,task2)

    理想情况下,您需要异步/等待从上到下(除非您处理的是CPU受限的算法)。在您的示例中,您可以通过使用
    Task.Delay
    而不是
    Thread.Sleep
    使方法异步,这样您就不需要
    Task.Run
    。您还应该使
    Main
    异步,并等待
    任务。当所有的
    完成时。您发布的代码似乎满足您所述的要求。如果您在重新组合方法以使用实际的
    async
    方法而不是
    Task.Run()
    时遇到问题,您的问题需要显示该代码。我们根本不清楚您需要什么帮助,也不清楚为什么网站上已有的数千个异步/等待问题中没有一个没有解决您的问题。“异步操作并行执行。”-您确定吗?(我在这里使用
    Thread.Sleep
    来模拟CPU受限的工作)。请看原因。我的意思是在不同的线程中执行一次。对不起,我的示例有点搞砸了。关键是异步并不一定意味着任务运行在不同的线程中。在我提供的示例中,所有内容都与调用方法在同一线程中同步运行。您可以将其与使用
    Task.Run
    in.强制不同线程时发生的情况进行比较。在中,您可以看到通过挂起异步方法(直到延迟过去),我们实际上看到任务方法在一个线程(同步部分)中开始,然后(延迟完成后)在不同线程中恢复。我建议阅读关于线程与任务的主题。你能提供一个完整的工作示例吗?我是一个太多的傻瓜,我遇到了我不知道如何解决的错误。@Chad updated..var result1=task1.Result
    var result1=await task1语法。从维护的角度来看,采用它可能是一个好主意,因为
    .Result
    属性与死锁问题相关联,可能会在每次眼睛经过它时引起红旗和假警报。
    After Task1: 00:00:00.0037888
    After Task2: 00:00:00.0094963
    Sum: 11
    Final: 00:00:10.0126715
    
    var task1 = AsyncOperation1(2);
    var task2 = AsyncOperation1(5);
    
    
    var result1 = await task1;
    var result2 = await task2;