缩进lambda和嵌套动作

Cli*_* Ok 5 c# lambda coding-style task-parallel-library

当使用lambdas时,通常是在TPL上,我会因缩进而迷失...是否有一些最佳实践来格式化?例如,请使用以下代码:

Task t1 = factory.StartNew(() =>
{
    DoSomething();
}
.ContinueWith((t2) =>
{
    DoSomethingWhenComplete();
}, TaskContinuationOptions.OnlyOnRanToCompletion)
).ContinueWith((t3) =>
{
    DoSomethingOnError();
}, TaskContinuationOptions.OnlyOnFaulted);
Run Code Online (Sandbox Code Playgroud)
  1. 我的"缩进"是否正确?
  2. 在那个例子中,我想执行t1,然后如果它完成OK,则执行t2,并在执行t3时执行错误.但看起来好像t3是t2的延续,而不是来自t1 ...我需要在该代码中修复什么才能获得正确的行为?我认为我迷失了那个缩进或遗漏了一些括号......

nos*_*tio 6

有一些最佳实践来格式化这个?

我不知道.我的格式看起来不错(除了下面的注释).或者,您可以只按照Visual Studio自动格式化(尝试从编辑器/高级菜单格式化文档).

在那个例子中,我想执行t1然后如果完成ok执行t2并且在执行t3时执行错误.但看起来t3是从t2继续,而不是从t1 ...我需要修复该代码以纠正行为?我认为我迷失了那个缩进或遗漏了一些括号......

您问题中的代码片段甚至无法编译.你可能想要这个:

Task t1 = factory.StartNew(() =>
{
    DoSomething();
});

t1.ContinueWith((t2) =>
{
    DoSomethingWhenComplete();
}, TaskContinuationOptions.OnlyOnRanToCompletion);

t1.ContinueWith((t2) =>
{
    DoSomethingOnError();
}, TaskContinuationOptions.OnlyOnFaulted);
Run Code Online (Sandbox Code Playgroud)

这可能有用,但你错过了另一种状态:OnlyOnCanceled.我宁愿处理t1同一个地方的所有完成状态:

Task t1 = factory.StartNew(() =>
{
    DoSomething();
}).ContinueWith((t2) =>
{
    if (t2.IsCanceled)
        DoSomethingWhenCancelled();
    else if (t2.IsFaulted)
        DoSomethingOnError(t1.Exception);
    else
        DoSomethingWhenComplete();
});
Run Code Online (Sandbox Code Playgroud)

这仍然可能缺少一件事:您的代码将在没有同步上下文的随机池线程上继续.例如,如果您调用ContinueWithUI线程,则无法访问DoSomething*方法内的UI .如果这不是您的预期,请明确指定任务计划程序以继续:

Task t1 = factory.StartNew(() =>
{
    DoSomething();
}).
ContinueWith((t2) =>
{
    if (t1.IsCanceled)
        DoSomethingWhenCancelled();
    else if (t1.IsFaulted)
        DoSomethingOnError(t1.Exception);
    else
        DoSomethingWhenComplete();
}, TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

如果您需要以.NET 4.0为目标但使用VS2012 +作为开发环境,请考虑使用async/awaitMicrosoft.Bcl.Async不是ContinueWith.代码更容易,更易读,并且可以为您提供结构化的错误处理try/catch.

如果你不能使用async/await,可以考虑使用Task.Then模式由Stephen Toub进行任务链接(这里有更多细节).