I've got a helper method that takes a lambda to execute within a try/catch/finally block, e.g.
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..
}
}
I would now like to create an async version that accepts an async lambda.
(Note, I've read and agree with Stephen Toub's posts on async over sync, but that doesn't apply here as the crux of the method, where asynchrony is or isn't beneficial, is supplied by the consumer via a lambda.)
I can copy and paste the above, mark it as async
, change the return type to Task
, add "Async" to it's name, change the type of the process
paramter to Func<object[,],Task>
and change
process(valueArray);
to
await process(valueArray);
and everything works fine. But I'd like to avoid repeating all the code in the try/catch/finally. Is there a clean way to achieve this without repeated code?
So far the best solution I've got is:
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());
}
but it's messy and the exceptions aren't handled. I'm wondering if there's another way?