如何通知异常并继续
本文关键字:异常 继续 通知 何通知 | 更新日期: 2023-09-27 18:19:45
Am正在编写一个库(作为Nuget包分发),它允许用户为一个存储库配置多个"读取器"。它遍历每个读卡器,并通过第一个可用的读卡器访问存储库。
读卡器具有可用状态,不可用也不例外。但是,还有一些其他异常情况需要通知调用应用程序。通知之后,程序应该能够尝试使用下一个读取器。
这些是我考虑过的选项
- 抛出一个异常:这里的问题是控制流返回
- 积累状态和回报:读者还有其他东西要回报,我不愿意将状态与它捆绑在一起
- 抛出这样的异常:看起来很可怕:)就像它可能会创建孤立线程或内存泄漏
- 事件:不确定如何通过事件进行
下面是一个协调器的示例,它将返回结果和处理过程中发生的任何异常。
public class Coordinator<T> where T: new()
{
public async Task<Tuple<IEnumerable<T>, AggregateException>> GetResultsAsync()
{
var tasks = new Task<T>[10];
for(int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => GetResult(i));
}
var results = new List<T>();
var exceptions = new List<Exception>();
foreach(var item in tasks)
{
try
{
var result = await item;
results.Add(result);
}
catch(Exception e)
{
exceptions.Add(e);
}
}
return Tuple.Create<IEnumerable<T>, AggregateException>(results, new AggregateException(exceptions));
}
private T GetResult(int i)
{
if (i % 2 == 0) throw new Exception("Result cannot be even.");
return new T();
}
}
由于应用程序应该继续,在调用方看来,这些都不是例外。异常应始终中止。
我会在内部做一些类似于.NET的事情,并有一个事件。
public class ReaderFailedEventArgs : EventArgs
{
public ReaderFailedEventArgs (IReader reader, Exception failure)
{
}
// [.. Two read only properties here ..]
}
public class Worker
{
public event EventHandler<ReaderFailedEventArgs> ReaderFailed = delegate{};
public IEnumerable<Data> Process()
{
foreach (var reader in _readers)
{
try
{
return reader.Read();
}
catch (Exception ex)
{
ReaderFailed(this, new ReaderFailedEventArgs(reader, ex);
}
}
// now, this is a real exception since user expects to get data
throw new InvalidOperationException("All readers failed");
}
}
为事件分配一个空委托(delegate{}
)允许我们使用该事件,而不必检查它是否为空(这也使事件线程安全)。