[英]How to queue/wait for TPL tasks to complete
我需要有關TPL和任務的幫助
這是我的情況:
我有一些產生任務的事件處理程序。 如果一個事件在其上一個任務完成之前被調用,我想在繼續之前等待(阻止)它。
我有一個同步方法,該方法在被調用時必須等到任何事件處理程序產生的所有任務完成后再繼續。
public void DoSomething()
{
// Expects any running tasks from OnEvent1(), OnEvent2(), OnEvent3()
// to be completed before proceeding.
}
public void OnEvent1()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent2()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent3()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
實際情況是:
OnSyncSettings() =>生成任務。 此后的所有后續調用都需要排隊。
OnAutoBackup() =>同步方法。 保存之前,請等待其他任務(例如,“獲取數據/同步”設置)完成。
我的問題很簡單:我該怎么做?
這種方法正確嗎?
每個事件處理程序都會記住其最后一個。 調用時,它將等待列表中的所有任務完成后再繼續。
對於同步方法,它需要等待所有任務(從每個事件處理程序)執行
Task _lastEvent1Task;
public void OnEvent1()
{
// Wait for all tasks to complete before proceeding
if (_lastEvent1Task!=null)
_lastEvent1Task.Clear();
// Spawns new task
_lastEvent1Task = Task.Factory.StartNew(()=>{ });
}
public void OnEvent3()
{
// Wait for any running tasks to complete before proceeding
if (_lastEvent1Task != null) _lastEvent1Task.Wait();
if (_lastEvent2Task != null) _lastEvent2Task.Wait();
...
// Proceed
}
謝謝!
[編輯]
當DoSomething()正在等待並且引發Event1時? 如果DoSomething()正在運行並且引發了事件該怎么辦?
OnEvents()
DoSomething() (調用時)
您描述的方法存在並發問題。 例如,在對_lastEvent1Task
進行null檢查_lastEvent1Task
,其他線程可能_lastEvent1Task
設置為null,從而導致NullReferenceException
。
我假設每個任務都應該同步運行,但有些不應阻塞。 實現此目標的最佳方法是使用僅利用單個線程的TaskScheduler
,您可以在此處找到示例。
var scheduler = new SingleThreadedTaskScheduler();
var taskFactory = new TaskFactory(scheduler);
對於非阻塞方法,您將得到以下內容:
public void NonBlockingMethod()
{
taskFactory
.StartNew(() => { /* Long-running work. */ })
.ContinueWith(t => { /* Update UI. */ });
}
對於阻塞方法,您將獲得:
public void BlockingMethod()
{
taskFactory
.StartNew(() => { /* Do work. */ })
.Wait();
}
在計划任務時,任務計划程序將僅使用一個線程來計划任務,從而確保所有任務都同步運行。
我認為您需要使用ParExtSamples中的任務計划程序。 通常,您需要為您的OnEvents的OrderedTaskScheduler(),然后等待所有預定的任務在DoSomething的完成()方法,或者干脆在同一OrderedTaskScheduler安排您DoSomething的()方法,它只會一次任務執行,預定在此之前,已經完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.