总之,我有一个长时间运行的进程,我使用任务并行库 (TPL) 在后台线程(支持取消)上运行。这个长期运行的任务的代码包含在Class Validation
, 当方法
public bool AsyncRunValidationProcess(TaskScheduler _uiScheduler,
CancellationToken _token, dynamic _dynamic = null)
{
try
{
// Note: _uiScheduler is used to update the UI thread with progress infor etc.
for (int i = 0; i < someLargeLoopNumber; i++)
{
// Cancellation requested from UI Thread.
if (_token.IsCancellationRequested)
_token.ThrowIfCancellationRequested();
}
return true;
}
catch (Exception eX)
{
// Do stuff. Display `eX` if cancellation requested.
return false;
}
}
从运行Class Validation
我可以很好地取消该过程。取消请求由适当的delegate
(如下所示)处理,并且工作正常(我不相信这是我的问题的原因)。
当我从另一个类运行此方法时Class Batch
,我通过“控制器”方法执行此操作
asyncTask = Task.Factory.StartNew<bool>(() => asyncControlMethod(), token);
进而调用该方法
valForm.AsyncRunValidationProcess(uiScheduler, token,
new List<string>() { strCurrentSiteRelPath }));
valForm
我的访问者在哪里Class Validation
,该方法运行良好,但是当我尝试取消时delegate
cancelHandler = delegate
{
UtilsTPL.CancelRunningProcess(asyncTask, cancelSource);
};
在哪里
public static void CancelRunningProcess(Task _task,
CancellationTokenSource _cancelSource)
{
try
{
_cancelSource.Cancel();
_task.Wait(); // On cross-class call it freezes here.
}
catch (AggregateException aggEx)
{
if (aggEx.InnerException is OperationCanceledException)
Utils.InfoMsg("Operation cancelled at users request.");
if (aggEx.InnerException is SqlException)
Utils.ErrMsg(aggEx.Message);
}
}
冻结/挂起(没有未处理的异常等)_task.Wait()
。这(我相信 - 通过测试)与我正在取消asyncControlMethod()
已调用的事实有关valForm.AsyncRunValidationProcess(...)
,因此它正在取消asyncControlMethod()
导致当前进程挂起。问题似乎在于将CancellationTokenSource
等传递给子方法。该IsCancellationPending
事件触发并终止控制方法,从而导致子方法挂起。
谁能告诉我我做错了什么或者(更相关地),我应该怎么做才能允许这样的取消程序?
注意:我试图生成一个子任务来运行valForm.AsyncRunValidationProcess(...)
,CancellationToken
但它没有奏效。
谢谢你的时间。