【发布时间】:2018-12-03 11:59:13
【问题描述】:
In the docs for TPL我找到了这一行:
从同一个先行词调用多个延续
但这没有进一步解释。我天真地假设您可以以类似模式匹配的方式链接 ContinueWiths,直到您找到正确的 TaskContinuationOptions。
TaskThatReturnsString()
.ContinueWith((s) => Console.Out.WriteLine(s.Result), TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith((f) => Console.Out.WriteLine(f.Exception.Message), TaskContinuationOptions.OnlyOnFaulted)
.ContinueWith((f) => Console.Out.WriteLine("Cancelled"), TaskContinuationOptions.OnlyOnCanceled)
.Wait();
但这并没有像我希望的那样工作,至少有两个原因。
- 延续已正确链接,因此第二个 ContinueWith 从第一个获得结果,即作为新任务实现,基本上是 ContinueWith 任务本身。我意识到可以继续返回字符串,但这不会是一个丢失其他信息的新任务吗?
- 由于没有满足第一个选项,任务就被取消了。这意味着永远不会满足第二组并且会丢失异常。
那么当他们说来自同一个先行词的多个延续时,他们在文档中是什么意思? 是否有合适的模式,还是我们只需将调用包装在 try catch 块中?
编辑
所以我想这就是我希望我能做的,注意这是一个简化的例子。
public void ProccessAllTheThings()
{
var theThings = util.GetAllTheThings();
var tasks = new List<Task>();
foreach (var thing in theThings)
{
var task = util.Process(thing)
.ContinueWith((t) => Console.Out.WriteLine($"Finished processing {thing.ThingId} with result {t.Result}"), TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith((t) => Console.Out.WriteLine($"Error on processing {thing.ThingId} with error {t.Exception.Message}"), TaskContinuationOptions.OnlyOnFaulted);
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
因为这是不可能的,所以我想我必须将每个任务调用包装在循环内的 try catch 中,这样我就不会停止进程,也不会在那里等待。我不确定正确的方法是什么。
有时解决方案只是盯着你的脸,这行不通?
public void ProccessAllTheThings()
{
var theThings = util.GetAllTheThings();
var tasks = new List<Task>();
foreach (var thing in theThings)
{
var task = util.Process(thing)
.ContinueWith((t) =>
{
if (t.Status == TaskStatus.RanToCompletion)
{
Console.Out.WriteLine($"Finished processing {thing.ThingId} with result {t.Result}");
}
else
{
Console.Out.WriteLine($"Error on processing {thing.ThingId} - {t.Exception.Message}");
}
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
【问题讨论】:
-
如果您想创建处理块的管道,请使用 TPL 数据流库。不要尝试自己构建它。
-
使用 try/catch 等待任务和处理潜在异常会更容易
-
@PanagiotisKanavos 我不知道这个库。我会看一下,但我想这对于我设想的用例来说有点过头了。
-
只需使用
await而不是手动添加延续。更好的错误处理语义是使用它的众多主要优势之一。 -
@Servy 如果它不是异步方法怎么办?公平地说,我当然可以把它变成 Async 方法。我想我有点愚蠢,如果我在循环中
Await会发生什么。循环是否继续迭代?如果是这样,那当然可以。
标签: c# task task-parallel-library continuewith