关于任务继续的问题
本文关键字:继续 问题 任务 于任务 | 更新日期: 2023-09-27 18:07:00
task1:
public Task SendMail(string email)
{
...
}
任务2:
public Task<int> SaveToDB(User user)
{
...
}
我需要做的:
- 当task1失败时,应返回"发送失败"信息
- 当任务1成功时,任务2开始
- 当task2失败时,应返回"保存失败"信息
- 当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;
}