C# 从异步任务方法返回“normal”变量
在我的一种方法中,我想创建一辆如下所示的汽车:C# 从异步任务方法返回“normal”变量,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,在我的一种方法中,我想创建一辆如下所示的汽车: public string[] CreateCar() { string[] wheels = CreateWheels(); // Also add motor and other stuff here string[] motor = ...; return new string[][]{ wheels, motor, ... }; } 这里创建了四个轮子,它们彼此不依赖。 因此,我可以将它们放在多个任务中
public string[] CreateCar()
{
string[] wheels = CreateWheels();
// Also add motor and other stuff here
string[] motor = ...;
return new string[][]{ wheels, motor, ... };
}
这里创建了四个轮子,它们彼此不依赖。
因此,我可以将它们放在多个任务中,并且可以并行处理。在我的实际代码中,这在并行for循环中是不可能的
public string[] CreateWheels()
{
Task FL = Task.Run(() => CreateWheel("front left");
Task FR = Task.Run(() => CreateWheel("front right");
Task BL = Task.Run(() => CreateWheel("back left");
Task BR = Task.Run(() => CreateWheel("back right");
// Here I really want to wait for all wheels to be created!
// STOP THE PROCESS HERE UNTIL ALL WHEELS ARE COMPLETED!!!
string[] wheels = await Wask.WhenAll(FL, FR, BL, BR);
return wheels;
}
一个轮子是这样创建的:
public string CreateWheel(string position)
{
// Here a wheel is created, whatever it takes :)
return "wheel " + position;
}
我现在的问题是:
为了编译代码,它迫使我将CreateWheels标记为异步方法。否则我不能用等待。
⇒ 但这迫使我将其返回值更改为任务
⇒ 但是,我需要在CreateCar方法中的CreateWheels前面放置一个wait,以便获取字符串数组,而不是任务本身
⇒ 然后循环重复,因为现在CreateWheels中有一个等待,迫使我使其异步。。。等等,等等
这个循环一直重复,直到最后出现一个void方法,在这里您不需要使用wait来提取返回值
如果我只想等待所有轮子在标记点完成,那么这个循环的出路是什么?如果你想同步,那么Task.WaitAll可能会有帮助,即 Task.WaitAllFL、FR、BL、BR; 变量轮=新[]{FL.Result,FR.Result,BL.Result,BR.Result}; 如果希望这是异步的,则需要将方法设为async[Value]任务,并在整个过程中传播异步性。异步是粘着的——它粘着一切;但是: 字符串[]轮=等待任务。当所有FL、FR、BL、BR;
然而,坦率地说,我怀疑在这种情况下两者都没有必要;并行性并不便宜,而且可能会增加比它在这里所值的更多的开销。如果您希望这是同步的,那么Task.WaitAll可能会有所帮助,即
string[] wheels = Wask.WhenAll(FL, FR, BL, BR).Result;
Task.WaitAllFL、FR、BL、BR;
变量轮=新[]{FL.Result,FR.Result,BL.Result,BR.Result};
如果希望这是异步的,则需要将方法设为async[Value]任务,并在整个过程中传播异步性。异步是粘着的——它粘着一切;但是:
字符串[]轮=等待任务。当所有FL、FR、BL、BR;
然而,坦率地说,我怀疑在这种情况下两者都没有必要;并行性并不便宜,而且可能会增加比它在这里所值的更多的开销
string[] wheels = Wask.WhenAll(FL, FR, BL, BR).Result;
我会做你想做的。这些单独的任务仍将并行运行
缺点是调用线程将阻塞,直到这些任务全部解决
我会做你想做的。这些单独的任务仍将并行运行
缺点是调用线程将阻塞,直到这些任务全部解决。可以通过使用Task.Run启动多个任务来实现并行性,但是为什么不使用专门的工具(如库)来完成任务呢?您不仅可以避免使用该属性,该属性与wait结合使用时会导致严重的死锁,而且还可以定义最大并行度作为奖励:
var wheelNames = new[] { "front left", "front right", "back left", "back right" };
string[] wheels = wheelNames
.AsParallel()
.AsOrdered()
.WithDegreeOfParallelism(4)
.Select(x => CreateWheel(x))
.ToArray();
可以通过使用Task.Run启动多个任务来实现并行性,但是为什么不使用专门的工具来完成任务,比如库呢?您不仅可以避免使用该属性,该属性与wait结合使用时会导致严重的死锁,而且还可以定义最大并行度作为奖励:
var wheelNames = new[] { "front left", "front right", "back left", "back right" };
string[] wheels = wheelNames
.AsParallel()
.AsOrdered()
.WithDegreeOfParallelism(4)
.Select(x => CreateWheel(x))
.ToArray();
除非CreateCar是一个要求特殊性的方法,否则我不明白为什么要使用Task.Run来执行它;应该work@UnholySheep:哦,太好了!那么,所有的任务都是并行执行的吗?您不想编写代码有什么原因吗?正如其他人提到的,异步在某种程度上具有传染性。根据这段代码嵌套的深度,交换所有内容可能会有点痛苦,但这比尝试调试任务IMO上使用.Result可能导致的任何死锁条件更痛苦。除非CreateCar是一种特殊要求的方法,否则我不明白为什么要使用task.Run来执行它。string[]轮子=任务时FL、FR、BL、BR结果;应该work@UnholySheep:哦,太好了!那么,所有的任务都是并行执行的吗?您不想编写代码有什么原因吗?正如其他人提到的,异步在某种程度上具有传染性。根据这段代码嵌套的深度不同,交换所有内容可能会有点痛苦,但这比尝试调试任何死锁条件更痛苦。任务结果IMO。非常感谢!如果下面的代码取决于CreateWheels的结果,那么无论如何都无法避免调用线程为block?而不是使用WhenAll.Result为什么不使用WaitAll,因为它是WhenAll的同步对应项?@TylerHundley也可以。WhenAll将一次性展开所有任务,并留给您一个正常的字符串数组。如果你把我的答案和马克的相比,你会发现即使打电话给WaitAll,他仍然必须这么做
处理多项任务并多次调用结果。但这只是偏好。很好,谢谢!如果下面的代码取决于CreateWheels的结果,那么无论如何都无法避免调用线程为block?而不是使用WhenAll.Result为什么不使用WaitAll,因为它是WhenAll的同步对应项?@TylerHundley也可以。WhenAll将一次性展开所有任务,并留给您一个正常的字符串数组。如果你把我的答案和Marc的相比,你会发现即使打了WaitAll,他仍然要处理好几项任务,并多次打电话给Result。但这只是偏好。