簡體   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