我试图找到执行以下流的最佳方法
2-4中的所有流都应该在一个与1不同的线程中完成,因此一旦动作1调用操作2,它就会继续做其他事情。
目前,我的流看起来是这样的(这是2-4,在1之后调用):
private void PerformActionAsync(List<long> XIds)
{
var affectedYIds = XIds.AsParallel().SelectMany(xId =>
{
return GetAffectedYIdsLongRunning(xId);
}).Distinct();
affectedYIds.ForAll(yId=>
{
ExcuteLongRunningAction(yId);
});
}这不能工作,因为SelectMany和ForAll仍然阻塞调用线程,我可以用新的任务创建替换ForAll,但是SelectMany仍然会阻塞调用线程。如何以真正的异步方式执行SelectMany?
目前,我最好的解决方案是用Taks.Run包装整个方法实现,问题是是否有更好的方法。
发布于 2015-01-08 12:08:39
您可以将代码包装在Task.Run中并返回该任务。这将使一切在后台运行。
下面的单元测试显示了使用情况:
[TestClass]
public class PLinqTests
{
private static readonly Stopwatch Watch = Stopwatch.StartNew();
[TestMethod]
public async Task TestPerformAsync()
{
await PerformActionAsync(Enumerable.Range(0, 10));
}
private Task PerformActionAsync(IEnumerable<int> xIds)
{
return Task.Run(() =>
{
var affectedYIds = xIds
.AsParallel()
.WithDegreeOfParallelism(5)
.SelectMany(this.GetAffectedYIdsLongRunning)
.Distinct();
affectedYIds.ForAll(this.ExcuteLongRunningAction);
});
}
private void ExcuteLongRunningAction(int yId)
{
Thread.Sleep(1000);
Console.WriteLine("Executed {0} at {1}.", yId, Watch.Elapsed.Seconds);
}
private IEnumerable<int> GetAffectedYIdsLongRunning(int xId)
{
Thread.Sleep(1000);
Console.WriteLine("Getting Affected for {0} at {1}.", xId, Watch.Elapsed.Seconds);
return Enumerable.Range(30, 10);
}
}输出:
Getting Affected for 0 at 1.
Getting Affected for 1 at 1.
Getting Affected for 2 at 1.
Getting Affected for 4 at 2.
Getting Affected for 3 at 2.
Getting Affected for 5 at 2.
Getting Affected for 6 at 2.
Getting Affected for 7 at 3.
Getting Affected for 8 at 3.
Getting Affected for 9 at 3.
Executed 32 at 3.
Executed 31 at 3.
Executed 30 at 4.
Executed 34 at 4.
Executed 33 at 4.
Executed 37 at 4.
Executed 36 at 4.
Executed 35 at 5.
Executed 39 at 5.
Executed 38 at 5.https://stackoverflow.com/questions/27836955
复制相似问题