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