2013-12-11 217 views
-1
TaskScheduler ts= TaskScheduler.FromCurrentSynchronizationContext(); 
try 
{ 
    Task<T> task1 = ... 
    task1.ContinueWith(t => 
    { 
     ... 
     Task<T> task2 = ... 
     task2.ContinueWith(u => 
     { 
      ... 
      Task<T> task3 = ... 
      task3.ContinueWith(w => 
      { 
       ... 
      }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
     }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
    }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
} 
catch(Exception) 
{ 
    MessageBox.Show("..."); 
}  

嗨。我有一些代码(如上)。这对我不起作用。我有三个工作在服务器端但修改UI的任务,所以它们都应该在UI线程中生成。更重要的是:如果第二个任务失败,第三个任务不能运行,而第二个任务只有在第一个成功完成后才能运行。所以如果第一个以失败告终,我的任务树应该抛出异常并中断其余的操作。如何以最简单的方式实现这一目标?按任务投掷异常

UPDATE

现在我的代码看起来像

private async void SomeMethod() 
{ 
... 
try 
{ 
     var r1 = await Method1(...); 
     var r2 = await Method2(...); 
    var r3 = await Method3(...); 
} 
catch 
{ 
     MessageBox.Show("..."); 
} 
} 

private Task<...> Method1(...) 
{ 
    Task<...> task = Task<...>.Factory.StartNew(() => 
    { 
     ... 
     try 
     { 
       // Result is null (but that's ok) so 'index out of range exception' is thrown 
       // It calls my method MyException with this exception (but I don't know in 
       // which thread and how to catch this (shouldn't be catch by async SomeMethod?) 
       result = ....Results[0]; 
     } 
     catch (Exception ex) 
     { 
       MyException(ex); 
     } 
    return result; 
    }); 
    return task; 
} 

public void MyException(Exception ex) 
{ 
    throw ex; 
} 

但我仍然不能赶上例外。

编辑 已解决。我不明白的异常(只是方法1忽略)和:

var r1 = await Method1(...); 
if(r1!=null) 
{ 
    var r2 = await Method2(...); 
    var r3 = await Method3(...); 
} 
else 
{ 
    ...do sth instead of catching ex 
} 

回答

4

最简单的方法是用在这里await,因为它提供了错误处理,你想用很少的努力语义;让你写代码,好像它是常规的同步代码:

try 
{ 
    var firstResult = await SomethingAsync(); 
    var secondResult = await SomethingElseAsync(firstResult); 
    var finalResult = await AnotherThingAsync(secondResult); 
} 
catch 
{ 
    //handle an exception thrown by any of the above async operations. 
} 

如果你不能做到这一点(由于是在.NET 4.0),那么你可以使用Then方法描述here也得到了语义你想:

var finalTask = SomethingAsync() 
.Then(firstResult => SomethingElseAsync(firstResult)) 
.Then(secondResult => AnotherThingAsync(secondResult)); 

finalTask.ContinueWith(t => HandleError(t.Exception), 
    TaskContinuationOptions.OnlyOnFaulted); 

Then实质上是ContinueWith通话,但使用不同的错误处理语义。如果任务继续发生异常,则Then只是传播该异常,而不是运行延续。 ContinueWith只是继续并吞下异常。

+0

我觉得你的解决方案吸引我,但我无法处理异常。我在.NET 4.5,所以我试图用 尝试 { ... } 赶上(AggregateException前) { MessageBox.Show(...); } 但这并没有从另一个线程捕获异常。任何评论? –

+0

@ user2248836使用'Wait'不是异步的,因为我提供的两个解决方案都是。但是,如果这不处理错误,则表示该任务未被标记为故障。要么这个错误是完全不相关的,要么这个任务本身就是创建出错的新任务,但它不会将其标记为故障。如果是这样的话,解决方案就是解决这个问题,所以你不能从这个位置开始。 – Servy

+0

我其实是喜欢你说的,这个“wait”来自另一个stackoverflow的帖子。 我的解决方案在'SomethingAsync();'中出现故障,出现异常,但对我的'catch'不可见。那我该如何解决这个问题? –