提问人:The_Matrix 提问时间:8/20/2023 最后编辑:The_Matrix 更新时间:8/20/2023 访问量:35
如何对具有最新上下文的多个并发任务执行一次取消/异常清理?
How do I perform cleanup of cancellation/Exceptions on multiple Concurrent Task's with newest context once?
问:
我正在编写一个桌面应用程序来控制一个小型 XY 阶段,遵循 MVP 架构。有一个 UI 线程,该线程发送到使用它们的 Operation 线程,并执行实际控制。Operation 线程在使用新事件时并发运行其硬件控制逻辑。存在覆盖当前任务(例如停止然后开始执行)的一个或多个新事件的情况。我希望能够取消任务、执行特定的清理和处理错误,例如使用操作线程中提供的最新上下文。ViewEvent
ViewEvent.Stop
ViewEvent.MoveRight
ViewEvent.MoveLeft
ViewEvent
LostConnectionException
我尝试运行一个循环,该循环从 a 读取并执行 's without 并利用它来处理取消/失败清理。生成任务的业务逻辑将在 Presenter 内部执行。async
BlockingCollection<ViewEvent>
async Task
await
Task.ContinueWith
public async Task HandleEventsBlocking()
{
foreach (var viewEvent in _viewEventsQueue.GetConsumingEnumerable())
{
switch (viewEvent)
{
case ViewEvent.Start:
Presenter.HandleStartAsync(_cts.Token).ContinueWith((task) =>
{
if (task.IsFaulted)
{
// Clean up and cancel all other tasks.
foreach (var innerException in task.Exception.InnerExceptions)
{
Console.WriteLine($"Caught exception: {innerException.Message}");
}
_cts.Cancel();
}
else if (task.IsCanceled)
{
// Clean up.
await Presenter.CleanUp();
}
});
break;
case ViewEvent.Faulty:
Presenter.HandleFaultyAsync(_cts.Token).ContinueWith((task) =>
{
if (task.IsFaulted)
{
// Clean up and cancel all other tasks.
foreach (var innerException in task.Exception.InnerExceptions)
{
Console.WriteLine($"Caught exception: {innerException.Message}");
}
_cts.Cancel();
}
else if (task.IsCanceled)
{
// Clean up.
await Presenter.CleanUp();
}
});
break;
case ViewEvent.Stop:
_cts.Cancel();
break;
case ViewEvent.Reset:
_cts.Dispose();
_cts = new CancellationTokenSource();
break;
}
}
}
public async Task HandleStartAsync(CancellationToken token)
{
await Task.Run(async () =>
{
token.ThrowIfCancellationRequested();
await Task.Delay(2000); // Simulated work. Would be passed token.
token.ThrowIfCancellationRequested();
});
}
public async Task HandleFaultyAsync(CancellationToken token)
{
await Task.Run(async () =>
{
token.ThrowIfCancellationRequested();
await Task.Delay(2000); // Simulated work that failed. Would be passed token.
throw new InvalidOperationException("FAILED ON PURPOSE");
});
}
但是,这种方法不起作用,因为每个人都可能会执行重复的清理工作。async Task
将添加一个额外的布尔标志,该标志在 之前运行,并在所有执行时使用 退出,然后执行清理。该标志将因失败而设置一次,随后将跳过设置它。PerformCleanUp
switch
Task.WaitAll
async Task
Task
ContinueWith
答: 暂无答案
评论
HandleEventsBlocking
async
ThreadPool
ThreadPool
async/await
async/await