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

C# 等待与并行

C# 等待与并行,c#,async-await,C#,Async Await,考虑以下呼吁: Getstuff(await getFoo, await getBar, await getQuux); 内部Getstuff: var fooLookup = getFoo?.Entries.ToLookup(x => x.Something); var barDictionary = getBar?.Entries.ToDictionary(x => x.Something); var quuxDictionary = getQuux.Entries.ToDi

考虑以下呼吁:

Getstuff(await getFoo, await getBar,  await getQuux);
内部
Getstuff

var fooLookup = getFoo?.Entries.ToLookup(x => x.Something);
var barDictionary = getBar?.Entries.ToDictionary(x => x.Something);
var quuxDictionary = getQuux.Entries.ToDictionary(x => x.Something);
Task<getFooLookup> fooLookup1;
Task<getBarDictionary> barDictionary1;
Task<getQuuxDictionary> quuxDictionary1;

Task.WaitAll(fooLookup1 = getFoo, barDictionary1 = getBar, quuxDictionary1 = getQuux);

var fooLookup = fooLookup1.Result.Entries.ToLookup(x => x.Something); 
var barDictionary = barLookup1.Result?.Entries.ToDictionary(x => x.Something); 
var quuxDictionary = quuxLookup1.Result?.Entries.ToDictionary(x => x.Something);
我的印象是,这错过了一个并发机会,可以通过以下方式提供:

Getstuff(getFoo, getBar, getQuux);
Getstuff

var fooLookup = getFoo?.Entries.ToLookup(x => x.Something);
var barDictionary = getBar?.Entries.ToDictionary(x => x.Something);
var quuxDictionary = getQuux.Entries.ToDictionary(x => x.Something);
Task<getFooLookup> fooLookup1;
Task<getBarDictionary> barDictionary1;
Task<getQuuxDictionary> quuxDictionary1;

Task.WaitAll(fooLookup1 = getFoo, barDictionary1 = getBar, quuxDictionary1 = getQuux);

var fooLookup = fooLookup1.Result.Entries.ToLookup(x => x.Something); 
var barDictionary = barLookup1.Result?.Entries.ToDictionary(x => x.Something); 
var quuxDictionary = quuxLookup1.Result?.Entries.ToDictionary(x => x.Something);
Task-woulookup1;
任务1;
任务1;
Task.WaitAll(傻瓜库1=getFoo,barDictionary1=getBar,quuxDictionary1=getQuux);
var-woulookup=woulookup1.Result.Entries.ToLookup(x=>x.Something);
var barDictionary=barLookup1.Result?.Entries.ToDictionary(x=>x.Something);
var quxdictionary=quxlookup1.Result?.Entries.ToDictionary(x=>x.Something);
第二个选项是否可以并行化(如果可以),如果可以,我将面临哪些风险(例如,涉及数据库查找)?我可能遗漏了什么

编辑

这三个参数的指定方式如下:

async Task<foo> GetFoo(ICollection<Guid> stuffList) { .. some async code.. }
...
var getFoo = GetFoo(list);
async Task GetFoo(ICollection stuffList){..some async code..}
...
var getFoo=getFoo(列表);

您的场景非常模糊。在这里,我假设所有这三个等待的任务都已经并发运行,因此您的原始代码正在同步等待单个结果

首先,重要的是要指出,您对代码的拟议更改确实会对代码的基本行为造成实质性和有害的更改。如果代码可能允许异步等待完成,那么建议的更改将强制线程同步等待完成。这应该避免

我认为这是相当明显的,但从评论中判断,有人对我的意图感到困惑,因此这是明确的警告。考虑到这一点

忽略语法错误的第二个示例可以(而且应该)简化为:

Task.WaitAll(getFoo, getBar, getQuux);

var fooLookup = getFoo.Result.Entries.ToLookup(x => x.Something); 
var barDictionary = getBar.Result?.Entries.ToDictionary(x => x.Something); 
var quuxDictionary = getQuux.Result?.Entries.ToDictionary(x => x.Something);
但在现实中,如果您的方法本身并不是一个天生的异步操作,那么您不应该强迫它这样做。调用方可以根据需要执行以下操作:

Task.WaitAll(getFoo, getBar, getQuux);
GetStuff(await getFoo, await getBar, await getQuux);
WaitAll()
强制执行示例的同步行为。再说一次,这并不是可取的。只是为了与您的示例保持一致,这是必需的

这样,在您尝试将结果传递给
GetStuff()
之前,所有三个任务都可以确保已经完成,
GetStuff()
可以保持其良好、简单的同步自我

使用
await
只会帮助解压异常,使其更易于处理、记录等。当然,您可以使用例如
getFoo.Result
而不是
await getFoo

但你根本不需要这个!假设这三个任务都已经在运行,那么依次等待这三个任务并不会阻止它们同时运行。即使第一个是最后一个完成的,当其中一个完成时,其他两个也将完成,等待的将立即完成

重要的是,这样做可以防止线程在等待结果可用时被阻塞。这比您提出的作为替代方案的同步等待要好得多


换句话说,您的原始代码很好,并且比您作为替代方案提出的代码要好。不要更改它。

如果您想要实现并行性,并且有3种方法返回say
Task
Task
Task
,非常简单:首先启动所有任务,但不要等待任何任务,然后再等待,或者将所有任务与
wait Task一起。WhenAll()
(理想情况下;否则不太适合使用blocking
Task.WaitAll()
),或者分别使用
wait
来处理每个任务。例如:

Task<T1> getFooTask = GetFoo();
Task<T2> getBarTask = GetBar();
Task<T3> getQuuxTask = GetQuux();
// All tasks started (or at least queued) now, potentially (probably) running in parallel

await Task.WhenAll(getFooTask, getBarTask, getQuuxTask);
// All tasks complete now
或许:

Getstuff(await getFooTask, await getBarTask,  await getQuuxTask);
您也可以使用
.Result
而不在此时阻塞,但再次使用
wait
重构效果更好

要单独等待它们(并且仍然实现并行性),只需删除
await Task.WhenAll()


作为旁注,删除
wait Task.WhenAll()
是一个简单的例子,展示了在已完成的任务上使用
wait
而不是
.Result
的好处。如果使用
.Result
而不是
.Result
,行为将从非阻塞变为阻塞。

您的代码示例太不完整,无法对其行为进行评论。如果
getFoo
/
getBar
/
getQuux
是任务,那么代码已经在并发运行。@StephenCleary即使在第一种情况下我们有三个等待?@OtávioDécio确实,我们知道表达式是可等待的,因此解析为
任务,但我们不知道它解析为的任务是何时创建的,或者它实际上何时开始执行g无论
任务
代表什么操作。这将取决于代码的具体情况。@Evk描述程序的每一个可能的实现以及所有实现的具体语义太宽泛了。有很多不同的编写程序的方法,它们的语义会有很大的差异。@Servy:但是你解释了上面的答案有什么不正确的地方。甚至没有什么用处。@Servy我很欣赏Peter的礼貌,这在这个网站上是非常缺乏的。@PeterDuniho首先,你在多个地方特别声明你在做假设,而你没有这些假设的基础,所以你的结论是有根据的因此,这些毫无根据的假设是毫无意义的。根据未显示的代码的具体情况,您提出的更改也会产生各种各样的影响。在任何情况下,它都不会产生您所解释的影响,但实际影响将有多种可能性。您对
的评估仍在等待
也完全不正确,只是完全不正确。@PeterDuniho 4)当一个问题没有提供足够的信息来回答时,适当的反应是努力解决这个问题,使它实际上包含eno