gpt4 book ai didi

c# - 异步任务的顺序处理

转载 作者:IT王子 更新时间:2023-10-29 04:11:12 46 4
gpt4 key购买 nike

假设以下同步代码:

try
{
Foo();
Bar();
Fubar();
Console.WriteLine("All done");
}
catch(Exception e) // For illustration purposes only. Catch specific exceptions!
{
Console.WriteLine(e);
}

现在假设所有这些方法都有一个 Async 对应物,并且出于某种原因我必须使用它们,所以简单地将整个方法包装在一个新任务中不是一个选项。
我将如何实现相同的行为?
“相同”的意思是:

  1. 如果抛出异常,则执行异常处理程序。
  2. 如果抛出异常,则停止执行以下方法。

我唯一能想到的是可怕:

var fooTask = FooAsync();
fooTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fooTask.ContinueWith(
t =>
{
var barTask = BarAsync();
barTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
barTask.ContinueWith(
t =>
{
var fubarTask = FubarAsync();
fubarTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fubarTask.ContinueWith(
t => Console.WriteLine("All done"),
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);

请注意:

  • 我需要一个适用于 .NET 4 的解决方案,所以 async/await 是不可能的。但是,如果它可以与 async/await 配合使用,请随意展示如何操作。
  • 我不需要使用 TPL。如果 TPL 不可能,则可以使用其他方法,也许是响应式扩展?

最佳答案

以下是它如何与 async 一起工作:

try
{
await FooAsync();
await BarAsync();
await FubarAsync();
Console.WriteLine("All done");
}
catch(Exception e) // For illustration purposes only. Catch specific exceptions!
{
Console.WriteLine(e);
}

如果您安装了(预发布)Microsoft.Bcl.Async package,这将适用于 .NET 4.0。


因为你卡在 VS2010 上,你可以使用 Stephen Toub's Then 的变体:

public static Task Then(this Task first, Func<Task> next)
{
var tcs = new TaskCompletionSource<object>();
first.ContinueWith(_ =>
{
if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
else if (first.IsCanceled) tcs.TrySetCanceled();
else
{
try
{
next().ContinueWith(t =>
{
if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
else if (t.IsCanceled) tcs.TrySetCanceled();
else tcs.TrySetResult(null);
}, TaskContinuationOptions.ExecuteSynchronously);
}
catch (Exception exc) { tcs.TrySetException(exc); }
}
}, TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
}

您可以这样使用它:

var task = FooAsync().Then(() => BarAsync()).Then(() => FubarAsync());
task.ContinueWith(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
var e = t.Exception.InnerException;
// exception handling
}
else
{
Console.WriteLine("All done");
}
}, TaskContinuationOptions.ExcecuteSynchronously);

使用 Rx,它看起来像这样(假设您没有公开为 asyncIObservable<Unit> 方法):

FooAsync().ToObservable()
.SelectMany(_ => BarAsync().ToObservable())
.SelectMany(_ => FubarAsync().ToObservable())
.Subscribe(_ => { Console.WriteLine("All done"); },
e => { Console.WriteLine(e); });

我觉得。无论如何,我不是 Rx 大师。 :)

关于c# - 异步任务的顺序处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14630770/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com