如何在 ASP.NET 中并行运行多个方法

问题描述 投票:0回答:2

我在 ASP.NET 控制台应用程序中有 8 个方法,例如

Fun1()
Fun2()
Fun3()
...等等。在我的控制台应用程序中,我按顺序调用了所有这些方法。但现在的要求是我必须使用并行编程概念来做到这一点。我读过 Java 中的任务和线程概念,但对 .NET 并行编程来说是全新的。

这是我在控制台应用程序中所需的方法流程,

如图所示,

Task1
Task2
应该并行运行,而
Task3
只会在前两个完成后才会发生。

每个任务中的函数(例如,

Fun3
Fun4
)应按顺序运行,一个接一个。
有人可以帮我吗?

c# asp.net asp.net-core parallel-processing task-parallel-library
2个回答
3
投票
WhenAll

举个例子,我创建了 X 个名为 FuncX() 的方法,如下所示:

Task1

在本例中,我们有 Func1、Func3、Func4、Func5 和 Func6。

因此我们调用方法并将它们传递给任务列表。

async static Task<int> FuncX() { await Task.Delay(500); var result = await Task.FromResult(1); return result; }

您有 2 个选择来获取结果:

var task1 = new List<Task<int>>(); task1.Add(Func3()); task1.Add(Func4()); var task2 = new List<Task<int>>(); task2.Add(Func1()); task2.Add(Func5()); task2.Add(Func6());

这只是灵感示例,您可以更改它并按照您想要的方式进行。


3
投票

// option1 var eachFunctionIsDoneWithAwait1 = await Task.WhenAll(task1); var eachFunctionIsDoneWithAwait2 = await Task.WhenAll(task2); var sum1 = eachFunctionIsDoneWithAwait1.Sum() + eachFunctionIsDoneWithAwait2.Sum(); Console.WriteLine(sum1); // option2 var task3 = new List<List<Task<int>>>(); task3.Add(task1); task3.Add(task2); var sum2 = 0; task3.ForEach(async x => { var r = await Task.WhenAll(x); sum2 += r.Sum(); }); Console.WriteLine(sum2);

 方法:
Task.Run

Task task1 = Task.Run(() =>
{
    Fun3();
    Fun4();
});
Task task2 = Task.Run(() =>
{
    Fun1();
    Fun5();
    Fun6();
});
Task task3 = Task.Run(async () =>
{
    await Task.WhenAll(task1, task2);
    Fun7();
    Fun8();
});

Task.Run
 上调用委托,而不是在专用线程上。如果您出于某种原因需要为每个任务创建专用线程,则可以使用带有 
ThreadPool
参数的高级
Task.Factory.StartNew
方法,如
here
所示。 需要注意的是,上述实现在出现异常时并不是最佳行为。如果

TaskCreationOptions.LongRunning

立即失败,最佳行为是尽快停止

Fun3()
的执行。相反,此实现将在传播错误之前执行所有三个函数
task2
Fun1
Fun5
。您可以通过创建
Fun6
 并在每个函数后调用 
CancellationTokenSource
来修复这个小缺陷,但这会很混乱。
另一个问题是,如果 

Token.ThrowIfCancellationRequested

task1
都失败,则只有
task2
的异常才会通过
task1
传播。解决这个问题并非易事。


更新:

这是解决部分异常传播问题的一种方法: task3

如果 
Task task3 = Task.WhenAll(task1, task2).ContinueWith(t => { if (t.IsFaulted) { TaskCompletionSource tcs = new(); tcs.SetException(t.Exception.InnerExceptions); return tcs.Task; } if (t.IsCanceled) { TaskCompletionSource tcs = new(); tcs.SetCanceled(new TaskCanceledException(t).CancellationToken); return tcs.Task; } Debug.Assert(t.IsCompletedSuccessfully); Fun7(); Fun8(); return Task.CompletedTask; }, default, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default) .Unwrap();

task1
都失败,
task2
将传播这两个任务的异常。
    

© www.soinside.com 2019 - 2024. All rights reserved.