我有一个名为TaskManager的Task.Factory.StartNew的包装器,我需要实现它以便在新线程中添加异常处理。这是我的班级:
public static class TaskManager
{
public static Task StartNew(Action action, IUserContextBase userContext, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action), userContext, null, onCompletedCallback);
}
public static Task StartNew(Action action, IUserContextBase userContext, CancellationToken cancellationToken, TaskCreationOptions taskCreationOptions, TaskScheduler taskScheduler, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action, cancellationToken, taskCreationOptions, taskScheduler), userContext, null, onCompletedCallback);
}
public static Task StartNew(Action action, IUserContextBase userContext, TaskCreationOptions taskCreationOptions, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action, taskCreationOptions), userContext, null, onCompletedCallback);
}
public static Task StartNew(Action<object> action, IUserContextBase userContext, object state, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action, state), userContext, null, onCompletedCallback);
}
public static Task StartNew(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions taskCreationOptions, TaskScheduler taskScheduler, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action, null, cancellationToken, taskCreationOptions, taskScheduler), null, null, onCompletedCallback);
}
public static Task StartNew(Action<object> action, object state, Action<System.Exception> onExceptionCallback = null, Action<Task> onCompletedCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action, state), null, onExceptionCallback, onCompletedCallback);
}
public static Task StartNew(Action action, Action<System.Exception> onExceptionCallback = null)
{
return AddContinueWithToTask(Task.Factory.StartNew(action), null, onExceptionCallback);
}
public static Task<TResult> StartNew<TResult>(Func<TResult> function, IUserContextBase userContext, CancellationToken cancellationToken)
{
return Task.Factory.StartNew(function, cancellationToken).ContinueWith(t =>
{
ManageException(t, userContext);
return t.Result;
}, TaskContinuationOptions.OnlyOnFaulted);
}
private static void ManageException(Task t, IUserContextBase userContext, Action<System.Exception> onExceptionCallback = null)
{
if (t.Exception != null)
if (onExceptionCallback != null)
onExceptionCallback(t.Exception);
else
t.Exception.Handle(ex =>
{
GlobalContainer.Unity.Resolve<IDiagnosticLogHandler>().LogError(userContext, ex, ErrorSeverity.Normal);
return true;
});
}
private static Task AddContinueWithToTask(Task task, IUserContextBase userContext, Action<System.Exception> onExceptionCallback = null, Action<Task> onCompletedCallback = null)
{
return task
.ContinueWith(t => ManageException(t, userContext, onExceptionCallback), TaskContinuationOptions.OnlyOnFaulted)
.ContinueWith(t2 => { if (onCompletedCallback != null) onCompletedCallback(t2); })
.ContinueWith(t => ManageException(t, userContext, onExceptionCallback), TaskContinuationOptions.OnlyOnFaulted);
}
但是,每当有人使用我的类(它返回一个Task),然后调用task.Wait()或task.WaitAll()之后,他们似乎得到一个异常,说任务已经(全部)被取消了。 Wait()或WaitAll()发生错误。我的TaskManager类有什么问题?
答案 0 :(得分:2)
您实际上是将原始任务的延续返回给调用者而不是实际任务。
您的延续时间为TaskContinuationOptions.OnlyOnFaulted
,这意味着只有在前因出现故障时才运行,否则取消。因此,您会看到来电者获得TaskCancelledException
。
换句话说,当实际任务运行至完成时,将取消继续。当实际任务出现故障时,如果使用TaskContinuationOptions.OnlyOnFaulted
,则“运行至完成
要修复它,您需要将实际任务返回给调用者,但添加延续并随身携带。
更新:要返回原始任务,只需使用本地变量。
public static Task StartNew(Action action, Action<System.Exception> onExceptionCallback = null)
{
var actualTask = Task.Factory.StartNew(action);
AddContinueWithToTask(actualTask, null, onExceptionCallback);
return actualTask;
}
...
答案 1 :(得分:0)
问题在于,您将t2
任务链接到一个永不运行的任务的末尾,因为它已设置为OnlyOnFaulted
。
试试这个: -
private static Task AddContinueWithToTask(Task task, object userContext, Action<System.Exception> onExceptionCallback = null, Action<Task> onCompletedCallback = null)
{
return task
.ContinueWith(t => {
if (t.IsFaulted)
ManageException(t, userContext, onExceptionCallback);
})
.ContinueWith(t2 =>
{
if (onCompletedCallback != null) onCompletedCallback(t2);
})
.ContinueWith(t => {
if (t.IsFaulted)
ManageException(t, userContext, onExceptionCallback);
})
;
}
来自Task.Continuewith
在当前任务完成之前,不会安排返回的任务执行 完成。如果通过continuationOptions参数指定的条件是 如果没有达到,延续任务将被取消而不是安排。