我的印象是控制流量與例外被認爲是一種不好的做法。TaskContinuationOptions.OnlyOnFaulted不考慮使用異常的流量控制?
那麼,爲什麼會做這樣的事情:
var task = Task.Factory
.StartNew(() => command.Execute());
task.ContinueWith(t =>
{
// success callback
}, TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t =>
{
Log.Error(string.Format("'{0}' failed.", command.GetType()), t.Exception);
// error callback
}, TaskContinuationOptions.OnlyOnFaulted);
時,你可以很容易地catch
內command.Execute()
的例外,是有我丟失的東西嗎?任務可以拋出與它們正在執行的代碼無關的異常嗎?
編輯: 怎麼樣,如果我們使用C#5的async
和await
關鍵字,你會說,這將是更好的,還是捕捉到所有真的沒有關係,如上面的例子?
public class AsyncFooCommand : AsyncCommandBase<Bar>
{
public override Bar Execute()
{
try
{
var bar = // Do something that can throw SpecificException
Successful = true;
return bar;
}
catch (SpecificException ex)
{
// Log
}
}
}
public static class AsyncCommandExecutor<T>
{
// NOTE: don't care about sharing this between instances.
// ReSharper disable StaticFieldInGenericType
private static readonly ILog Log = LogManager.GetLogger(typeof(Infrastructure.Commands.AsyncCommandExecutor<>));
// ReSharper restore StaticFieldInGenericType
public static async Task<T> Execute(IAsyncCommand<T> command, Action<T> success = null, Action error = null)
{
var task = Task.Factory
.StartNew(() =>
{
return command.Execute();
});
task.ContinueWith(t => Log.Error(string.Format("'{0}' failed, something terrible happened.", command.GetType()), t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
T result = await task;
if (success != null && command.Successful)
{
success(result);
}
if (error != null && !command.Successful)
{
error();
}
return result;
}
}
「任務可以拋出與它們正在執行的代碼無關的異常嗎?」是的 - 如果某個任務的線程被另一個線程中止,則該任務可能會拋出ThreadAbortException異常。這與任務相關的代碼無關。 –
很高興知道,感謝您的意見。對第二個例子有什麼想法? –
成功回調w/OnlyOnFaulted標誌? – Henrik