繁体   English   中英

线程安全的任务队列等待

[英]Thread-safe task queue await

我想做一件简单的事情(假设ContinueWith线程安全的):

readonly Task _task = Task.CompletedTask;

// thread A: conditionally prolong the task
if(condition)
    _task.ContinueWith(o => ...);

// thread B: await for everything
await _task;

问题:在上面的代码中, await _task立即返回,忽略是否有内部任务。

_task可以延长多个ContinueWith的扩展要求,我将如何等待所有这些都完成?


当然,我可以尝试以旧的线程安全方式进行操作:

Task _task = Task.CompletedTask;
readonly object _lock = new object();

// thread A
if(condition)
    _lock(_lock)
        _task = _task.ContinueWith(o => ...); // storing the latest inner task

// thread B
lock(_lock)
    await _task;

或者通过将任务存储在线程安全集合中并使用Task.WaitAll

但我很好奇第一个片段是否有一个简单的修复方法?

您的旧版本是可以的,除了在保持锁定时await 您应该在持有锁的同时将该_task复制到局部变量,释放锁,然后才await

但是,ContinueWith 工作流程不是 IMO 实现该逻辑的最佳方式。 在 async-await 成为语言的一部分之前,在 .NET 4.0 中引入了 ContinueWith。

在现代 C# 中,我认为最好这样做:

static async Task runTasks()
{
    if( condition1 )
        await handle1();
    if( condition2 )
        await handle2();
}
readonly Task _task = runTasks();

或者,如果您希望它们并行运行:

IEnumerable<Task> parallelTasks()
{
    if( condition1 )
        yield return handle1();
    if( condition2 )
        yield return handle2();
}
readonly Task _task = Task.WhenAll( parallelTasks() );

PS 如果条件是动态变化的,对于顺序版本,您应该在第一次等待之前将它们的值复制到局部变量。

更新:所以你是说你的线程 A 延长了该任务以响应一些动态发生的事件? 如果是,您的旧方法没问题,它很简单并且有效,只需修复那个lock(){ await... }并发错误。

从理论上讲,更清洁的方法可能类似于反应器模式,但不幸的是它要复杂得多。 这是我的开源示例,有点类似。 您不需要并发限制信号量,也不需要第二个队列,但您需要公开一个 Task 类型的属性,用TaskCompletionSource<bool>对其进行初始化,当第一个是发布,并在没有更多发布的任务后在 runAsyncProcessor 方法中完成该任务。

在您的原始代码await _task; 立即返回,因为task已完成。 你需要做

_task = _task.ContinueWith(...);

您不必使用锁。 您正在同一个线程中工作。 在代码的“锁定”版本中,您确实使用_task = _task.ContinueWith(...)这就是它起作用的原因,而不是因为锁定。


编辑:刚刚看到你想做_task = _task.ContinueWith(...); 在一个线程和_task = _task.ContinueWith(...)

这作为设计是相当糟糕的。 你永远不应该将线程和任务结合起来。 对于仅任务解决方案或仅线程解决方案,您应该使用 go。

如果您 go 用于仅任务解决方案(推荐),只需创建一个良好的工作任务序列,然后在每个任务上根据前一个任务的结果决定如何进行。

如果您将 go 用于纯线程解决方案,您可能希望使用ManualResetEvent句柄来同步您的任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM