调用Wait()或WaitAll()时,任务总是取消
本文关键字:任务 取消 WaitAll Wait 调用 | 更新日期: 2023-09-27 18:24:43
我有一个Task.Factory.StartNew的包装器,名为TaskManager,我需要实现它,以便在新线程中添加异常处理。这是我的课:
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。等待()或任务。WaitAll()之后,他们似乎得到了一个异常,表示任务(全部)已被取消。错误发生在Wait()或WaitAll()处。我的TaskManager类可能出了什么问题?
实际上是将原始任务的延续返回给调用者,而不是实际任务。
您的延续有TaskContinuationOptions.OnlyOnFaulted
,这意味着只有在先行件出现故障时才运行它,否则取消它。因此,您可以看到调用者得到TaskCancelledException
。
换句话说,当实际任务运行到完成时,Continuation将被取消。当实际任务出现故障时,Continuation将运行到完成,前提是使用了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;
}
...
问题是,您将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
上的MSDN
在当前任务已完成。如果通过continuationOptions参数指定的条件为如果未满足,则继续任务将被取消,而不是按计划执行。