Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.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_Task - Fatal编程技术网

C# 立即等待异步任务与先声明然后等待

C# 立即等待异步任务与先声明然后等待,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,让我们来看以下两个示例: 公共类MyClass { 公共异步任务Main() { var result1=“”; var result2=“”; var request1=await DelayMe(); var request2=await DelayMe(); 结果1=1; 结果2=2; } 专用静态异步任务DelayMe() { 等待任务。延迟(2000); 返回“”; } } 以及: 公共类MyClass { 公共异步任务Main() { var result1=“”; var res

让我们来看以下两个示例:

公共类MyClass
{
公共异步任务Main()
{
var result1=“”;
var result2=“”;
var request1=await DelayMe();
var request2=await DelayMe();
结果1=1;
结果2=2;
}
专用静态异步任务DelayMe()
{
等待任务。延迟(2000);
返回“”;
}
}
以及:

公共类MyClass
{
公共异步任务Main()
{
var result1=“”;
var result2=“”;
var request1=DelayMe();
var request2=DelayMe();
结果1=等待请求1;
结果2=等待请求2;
}
专用静态异步任务DelayMe()
{
等待任务。延迟(2000);
返回“”;
}
}
在第一个示例中,显示了通常如何编写
async await
代码,其中一件事情发生在另一件事情之后,并被正确地等待

第二个是首先调用
async Task
方法,但它正在
等待
稍后调用它

第一个示例需要超过
4000ms
一点的时间来执行,因为
wait
在发出第二个请求之前正在计算第一个请求;但第二个示例的时间略大于
2000ms
。之所以会出现这种情况,是因为只要执行步骤跨过
var request1=DelayMe(),任务实际上就会开始运行行,表示
request1
request2
并行运行。此时,
await
关键字似乎只是确保计算了
任务

第二种方法的感觉和行为类似于等待任务。当所有(request1,request2)
,但在这种情况下,如果两个请求中出现故障,您将立即获得异常,而不是等待所有内容计算,然后获得一个
聚合异常


我的问题是,当一个任务的结果不依赖于另一个任务的执行时,使用第二种方法并行运行多个
await
able
Task
s是否存在缺陷(性能或其他方面)?查看降低的代码,第二个示例似乎为每个等待的项生成等量的
System.Threading.Tasks.Task
1
,而第一个示例则没有。这是否仍在进行异步等待`状态机流?

使用第二种方法并行运行多个等待任务的缺点是并行性不明显。而不明显的并行性(换句话说,隐式多线程)是危险的,因为可能引入的bug是众所周知的不一致的,并且偶尔会被观察到。让我们假设在生产环境中运行的实际
DelayMe
如下所示:

private static int delaysCount = 0;

private static async Task<String> DelayMe()
{
    await Task.Delay(2000);
    return (++delaysCount).ToString();
}
private static int delayscont=0;
专用静态异步任务DelayMe()
{
等待任务。延迟(2000);
return(++delayScont).ToString();
}
按顺序等待的对
DelayMe
的调用将返回递增的数字。并行等待的呼叫偶尔会返回相同的号码

如果在这两个请求中出现故障,您将立即得到一个异常,而不是等待所有内容都计算,然后得到一个AggregateException

如果第一次请求失败,那么是。如果第二个请求失败,则为否,在该任务
wait
ed之前,您不会检查第二个请求的结果

我的问题是,当一个任务的结果不依赖于另一个任务的执行时,使用第二种方法并行运行多个等待的任务是否有缺点(性能或其他方面)?查看降低的代码,第二个示例生成的System.Threading.Tasks.Task1per waitied item数量与第一个示例相同,而第一个示例没有生成。这是否仍在通过同步等待状态机流

它仍在通过状态机流程。我倾向于推荐
wait Task.whalll
,因为代码的意图更加明确,但有些人不喜欢“即使有异常也要等待”的行为。另一方面是
任务。当所有的
总是收集所有异常时-如果您有快速失败行为,那么一些异常可以忽略

关于性能,并发执行会更好,因为您可以同时执行多个操作。由于
async
/
await
不使用额外的线程,因此不会出现线程池耗尽的危险


作为补充说明,我建议使用术语“异步并发”而不是“并行”,因为对许多人来说,“并行”意味着并行处理,即,
并行
或PLINQ,在这种情况下使用这种技术是错误的。

我看不出任何缺点,但如果我是为非依赖性任务这样做的,我会使用
Task.WhenAll()
。在某些情况下,您可能只想完成其中一项任务(其中一项可能是超时),在这种情况下,您可以使用
Task.whenny()
。我怀疑这个问题背后的实际问题是完全不同的。这两种等待的明显问题是,您可能必须等待最慢的任务完成,然后才能获得任何异常—任何提前完成的任务。如果你关心这些事情,尽管你不应该这样写任务。早期中止可以通过使用CancellationTokenSource来完成,例如,如果任何异步操作决定中止,将发出信号。如果您需要调用eg 3不同的服务获取数据,而不是在顶层等待任何故障,您可以将CancellationToken传递给工作函数,如果其中任何一个函数捕捉到异常,将发出通知。Th