【发布时间】:2016-05-02 21:35:29
【问题描述】:
我有一个辅助方法,它需要一个 lambda 在 try/catch/finally 块中执行,例如
public void ProcessSpreadsheet(string filename, Action<object[,]> process) {
try {
// Open MS Excel workbook
// Open sheet & extract data into valueArray
// ... more boiler plate ...
process(valueArray);
}
catch (FooException e) {
LogFoo(e.Message);
throw;
}
catch (BarException e) {
LogBar(e.Message);
throw;
}
finally {
// Close workbook, release resources, etc..
}
}
我现在想创建一个接受异步 lambda 的异步版本。
(请注意,我已阅读并同意 Stephen Toub 的 posts 关于异步优于同步,但这不适用于该方法的症结所在,其中异步是或无益,由消费者通过 lambda 提供。)
我可以复制粘贴上面的内容,将其标记为async,将返回类型更改为Task,在其名称中添加“Async”,将process参数的类型更改为Func<object[,],Task>并更改
process(valueArray);
到
await process(valueArray);
一切正常。但我想避免重复 try/catch/finally 中的所有代码。有没有一种简洁的方法可以在不重复代码的情况下实现这一目标?
到目前为止,我得到的最佳解决方案是:
public async Task ProcessSpreadsheetAsync(string filename, Func<object[,],Task> process) {
var asyncTaskComplete = new ManualResetEvent(false);
ProcessSpreadsheet(filename, async valueArray => {
await process(valueArray);
asyncTaskComplete.Set();
});
await Task.Run(() => asyncTaskComplete.WaitOne());
}
但它很混乱,并且没有处理异常。我想知道是否还有其他方法?
【问题讨论】:
-
您要避免重复哪些代码? try/catch/finally 代码?为什么在异步版本中通过
Task.Run运行代码?你到底想用异步版本实现什么? -
@YacoubMassad 是的,应该是 Func
,我已经解决了,谢谢。 -
这段代码真的有效吗?
process抛出的异常会被 catch 块捕获吗? -
是的,我想避免重复 try/catch/finally 代码。对于传入的 lambda 将从异步中受益的情况,我想要一个异步版本。例如,我使用同步版本从电子表格中计算总数,但我想要一个异步版本,在该版本中我对电子表格中的每一行进行网络调用。这会很慢,而且我想保持 UI 响应,所以我想在异步 lambda 中进行。
-
@YacoubMassad,不,你又是对的,没有发现异常:(。我想我需要的帮助比我想象的要多。
标签: c# asynchronous lambda async-await