【发布时间】:2015-02-18 09:31:45
【问题描述】:
我有一个异步运行某些工作包的通用类。它有可能取消所有任务的执行并同步等待取消的任务完成。在新事务(用户做某事)开始之前触发取消。这是必要的,因为异步任务和新事务会更改相同的对象,但异步任务会在假定事务之前的状态时执行此操作。
这是为什么这种行为如此重要的示例代码:
private void Transaction()
{
asyncExecution.AbortAllAsyncWork();
DoTransaction();
}
此方法被同步调用,DoTransaction 更改对象,这些对象在异步任务中也发生更改。例如列表可以在迭代时更改。
以前,我在传递同步任务调度程序的任务上使用 ContinueWith 方法实现了这种行为。总而言之,这很难理解,而且看起来有点脏。因此,我想知道是否可以使用新的 async-await 功能实现相同的行为。这里的问题在于here 描述的死锁。到目前为止出现死锁问题的代码:
public void RunAsync<TWork, TResult>(IIncrementalAsyncExecutable<TWork, TResult> executable, TWork initialWork) where TWork : class
{
Task workingTask = RunAsyncInternal(executable, initialWork, CancellationTokenSource);
if (IsRunning(workingTask))
{
workingTasks.Add(workingTask);
}
}
private async Task RunAsyncInternal<TWork, TResult>(IIncrementalAsyncExecutable<TWork, TResult> executable, TWork initialWork, CancellationTokenSource tokenSource) where TWork : class
{
while (!executable.WorkDone)
{
TResult result = await Task.Run(() => executable.CalculateNextStep(initialWork));
executable.SyncResult(result);
if (tokenSource.IsCancellationRequested)
{
return;
}
}
}
public void AbortAllAsyncWork()
{
CancellationTokenSource.Cancel();
foreach (Task workingTask in workingTasks)
{
if (IsRunning(workingTask))
{
workingTask.Wait(); // here is the deadlock problem
}
}
}
是否有可能通过新的 async-await 功能实现此行为而不会出现死锁?
【问题讨论】:
-
在旁注中,为什么你需要
RunAsyncInternal中的while循环? -
工作安排在药剂中,一旦完成,这些药剂就会同步回用户界面。
标签: c# .net multithreading asynchronous async-await