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

yr9zkbsy  于 11个月前  发布在  .NET
关注(0)|答案(2)|浏览(135)

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


的数据
如图所示,Task1Task2应该并行运行,而Task3只会在前两个完成后才发生。
每个任务中的函数(例如,Task1Fun3Fun4)应该依次运行。
有人能帮帮我吗?

vu8f3i0k

vu8f3i0k1#

解决这个问题的一种方法是使用WhenAll
举一个例子,我创建了X个方法,名称为FuncX(),如下所示:

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

字符串
在本例中,我们有Func1、Func3、Func4、Func5和Func6。
所以我们调用方法并将它们传递给一个Task列表。

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());


您有两个选项来获得结果:

// 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);


这只是灵感的例子,你可以改变它,按照你想要的方式去做。

k7fdbhmy

k7fdbhmy2#

下面是如何使用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上的委托,而不是专用线程上的委托。如果您有理由为每个任务创建一个专用线程,则可以使用带有TaskCreationOptions.LongRunning参数的高级Task.Factory.StartNew方法,如下所示。
应该注意的是,上述实现在出现异常的情况下并没有最佳行为。如果Fun3()立即失败,最佳行为将是尽快停止task2的执行。相反,此实现将执行所有三个函数Fun1。您可以通过创建一个CancellationTokenSource并在每个函数后调用Token.ThrowIfCancellationRequested来修复这个小缺陷,但这会很麻烦。
另一个问题是,如果task1task2都发生故障,则只有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();


如果task1task2都失败,task3将传播这两个任务的异常。

相关问题