关于任务继续的问题

本文关键字:继续 问题 任务 于任务 | 更新日期: 2023-09-27 18:07:00

task1:

public Task SendMail(string email)
 {
  ...
 }

任务2:

public Task<int> SaveToDB(User user)
 {
  ...
 }

我需要做的:

  1. 当task1失败时,应返回"发送失败"信息
  2. 当任务1成功时,任务2开始
  3. 当task2失败时,应返回"保存失败"信息
  4. 当task2成功时,应返回"保存成功"信息

请帮我找到一个解决方案:

public Task<string> SendAndSave(User user){
var task1 = SendMail(user.Email);
var task1Failed = task1.ContinueWith(t =>   
{
     var e = task1.Exception;
     return "Send Failed";
}, 
TaskContinuationOptions.OnlyOnFaulted | 
TaskContinuationOptions.ExecuteSynchronously);
var task2 = task1.ContinueWith(t =>
{
    var save = SaveToDB(user);
    try
    {
        int result = save.Result;
        return "Save Succeeded"; 
      }
     catch(AggregateException ae)
     {
          return "Save Failed";
      }
      },
      TaskContinuationOptions.NotOnFaulted); 
 return Task.Factory.ContinueWhenAny(new[] {task1Failed, task2}, t => t.Result);
 }

当我运行它时,我收到一个错误。

我调用它作为:

var result = SendAndSave(user).Result;

错误发生在:

public Task<string> SendAndSave(User user)
{
      ...
      return Task.Factory.ContinueWhenAny(new[] {task1Failed, task2}, t => t.Result);   //Here: A task was cancelled
 }

调试后,我有两个问题:

  • Q1:创建task1、task1Failed和task2后,每个的值CreationOption属性为"none",尽管其Status为"等待激活"。似乎所有的延续选项都是无效的

  • Q2:对于task的任务。工厂ContinueWhenAny(new[]{task1失败,task2},t=>t.Result(,让我们将其命名为"factoryTask"ContinueWhenAny似乎无效。在内部设置断点后关于task1失败、task2和factoryTask中的每一个,我偶尔可以看到尽管应在task1Failed或task2完成后进行。

有人能帮忙吗?谢谢

关于任务继续的问题

虽然我不完全理解你的问题,但我理解这里的问题,基本上你总是会有任务1失败或任务2完成,但不是两者都完成,另一个会被取消!所以在WaitOnAny调用中,如果它发现其中一个任务已经取消,它就会崩溃,这实际上取决于tasks参数的顺序,所以在上面的例子中,你先传递task1failed,所以如果这个任务完成了ContinueWhenAny会工作得很好,因为它检查的第一个任务已经完成,所以它不会检查另一个,但如果task1Failed没有运行,因此处于取消状态,ContinueWhenAny将抛出!

为了避免这种情况,您需要使用TaskCompletetionSource,并且运行的任务将设置该值,然后在最后返回tcs。任务结果

public Task<string> SendAndSave(User user){
var tcs = new TaskCompletionSource<string>();
var task1 = SendMail(user.Email);
var task1Failed = task1.ContinueWith(t =>   
{
     var e = task1.Exception;
     tcs.TrySetResult("Send Failed");
}, 
TaskContinuationOptions.OnlyOnFaulted | 
TaskContinuationOptions.ExecuteSynchronously);
var task2 = task1.ContinueWith(t =>
{
    var save = SaveToDB(user);
    try
    {
        int result = save.Result;
        tcs.TrySetResult("Save Succeeded"); 
    }
    catch(AggregateException ae)
    {
       tcs.TrySetResult("Save Failed"); 
    }
},TaskContinuationOptions.NotOnFaulted); 
 return tcs.Task.Result;
}