Concurrency in CSharp Cookbook中文翻译:5.2传播错误

发布时间:2024年01月04日

Problem 问题

You need a way to respond to errors that can happen in your dataflow mesh.
您需要一种方法来响应数据流网格中可能发生的错误。

Solution 解决方法

If a delegate passed to a dataflow block throws an exception, then that block will enter a faulted state. When a block is in a faulted state, it will drop all of its data (and stop accepting new data). The block in the following code will never produce any output data; the first value raises an exception, and the second value is just dropped:
如果传递给数据流块的委托抛出异常,则该块将进入故障状态。当一个块处于故障状态时,它将丢弃所有数据(并停止接受新数据)。下面代码中的块永远不会产生任何输出数据;第一个值引发异常,第二个值被丢弃:
var block = new TransformBlock(item =>
	{ 
		if (item == 1)
			throw new InvalidOperationException("Blech."); 
		return item * 2; 
	}); 
block.Post(1); 
block.Post(2);
To catch exceptions from a dataflow block, you should await its Completion property. The Completion property returns a Task that will complete when the block is completed, and if the block faults, the Completion task is also faulted:
要从数据流块捕获异常,应该等待它的Completion属性。Completion属性返回一个任务,该任务将在块完成时完成,如果块出现故障,则Completion任务也会出现故障:
try 
{ 
	var block = new TransformBlock(item =>
	{ 
		if (item == 1)
			throw new InvalidOperationException("Blech."); 
		return item * 2; 
	}); 
	block.Post(1); 
	await block.Completion; 
} 
catch (InvalidOperationException) 
{ 
	// The exception is caught here. 
}
When you propagate completion using the PropagateCompletion link option,errors are also propagated. However, the exception is passed to the next block wrapped in an AggregateException. The following example catches the exception from the end of a pipeline, so it would catch AggregateException if an exception was propagated from earlier blocks:
当您使用PropagateCompletion链接选项传播完成时,也会传播错误。然而,异常被传递到封装在AggregateException中的下一个块。下面的例子从管道的末端捕获异常,所以如果一个异常是从早期块传播的,它将捕获AggregateException:
try
{
? ? var multiplyBlock = new TransformBlock<int, int>(item =>
? ? {
? ? ? ? if (item == 1)
? ? ? ? ? ? throw new InvalidOperationException("Blech.");
? ? ? ? return item * 2;
? ? });
? ? var subtractBlock = new TransformBlock<int, int>(item => item - 2);
? ? multiplyBlock.LinkTo(subtractBlock,
? ? new DataflowLinkOptions { PropagateCompletion = true });
? ? multiplyBlock.Post(1);
? ? await subtractBlock.Completion;
}
catch (AggregateException)
{
? ? // The exception is caught here.
}
When you propagate completion using the PropagateCompletion link option,errors are also propagated. However, the exception is passed to the next block wrapped in an AggregateException. Each block wraps incoming errors in an AggregateException, even if the incoming error is already an AggregateException. If an error occurs early in a pipeline and travels down several links before it’s observed, the original error will be wrapped in multiple layers of AggregateException. The AggregateException.Flatten method simplifies error handling in this scenario.The following example catches the exception from the end of a pipeline, so it would catch AggregateException if an exception was propagated from earlier blocks:
当您使用PropagateCompletion链接选项传播完成时,也会传播错误。然而,异常被传递到封装在AggregateException中的下一个块。每个块将传入的错误包装在AggregateException中,即使传入的错误已经是AggregateException。如果错误发生在管道的早期,并且在观察到它之前沿着几个链接传播,那么原始错误将被包装在多层AggregateException中。AggregateException。Flatten方法简化了这种情况下的错误处理。下面的例子从管道的末端捕获异常,所以如果一个异常是从早期块传播的,它将捕获AggregateException:

Discussion 讨论

When you build your mesh (or pipeline), consider how errors should be handled. In simpler situations, it can be best to just propagate the errors and catch them once at the end. In more complex meshes, you may need to observe each block when the dataflow has completed.
当您构建网格(或管道)时,请考虑如何处理错误。在更简单的情况下,最好只传播错误并在最后捕获一次。在更复杂的网格中,您可能需要在数据流完成时观察每个块。
Alternatively, if you want your blocks to remain viable in the face of exceptions, you can choose to treat exceptions as another kind of data and let them flow through your mesh along with your correctly processed data items. Using that pattern, you can keep your dataflow mesh operational, since the blocks themselves don’t fault and continue processing the next data item. See Recipe 14.6 for more details.
或者,如果您希望您的块在面对异常时仍然可行,您可以选择将异常视为另一种数据,并让它们与正确处理的数据项一起流经网格。使用该模式,您可以保持数据流网格的可操作性,因为块本身不会出错并继续处理下一个数据项。参见Recipe 14.6了解更多细节。
文章来源:https://blog.csdn.net/a13407142317/article/details/135378270
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。