2016-03-24 89 views
-1

我有一個網站刮板,用分頁結果來刮擦網站。WaitAll阻止UI

對於每一頁我嘗試運行一個任務,使其更快,但凍結。

var pageCount = getPageCount(txtSearchQuery.Text); 
var tasks = new Task[pageCount]; 

var link = txtSearchQuery.Text; 
for (var i = 1; i <= pageCount; i++) 
{ 

    tasks[i-1] = new Task(new Action(() => { Scrape(link, i); })); 
    tasks[i-1].Start(); 
} 

Task.WaitAll(tasks); 
MessageBox.Show("Complete"); 

我做錯了什麼?

+0

'WaitAll'是一個阻塞操作。這些任務可以並行運行,但只要最長時間運行的任務完成,「WaitAll」將會被阻塞。 –

+0

*我做錯了什麼?*您正等待*完成所有任務。阻止當前(UI)線程。 –

+0

你有一個WPF應用程序,你爲什麼不使用'async' /'await'? – kai

回答

5

我假設你使用的是最新版本的.NET的支持異步/等待

更改您的方法簽名,使它異步和等待的使用Task.WhenAll你的任務的結果。這將釋放UI線程即。不會掛起用戶界面。

// normally you do not return void but a Task BUT with WPF events 
// (like on button click) void is required instead 
protected async void MyMethod() { 

    // Task.WaitAll(tasks); // replace this with 
    await Task.WhenAll(tasks); // this will not hang your UI 

    // rest of your code that you want to execute 
} 
+0

問題:在完成所有任務後,我們應該在哪裏放置我們希望執行的代碼?我認爲OP會想知道在哪裏使用這段代碼:) – J3soon

+0

@ J3soon - 緊接在等待之後。代碼將繼續處理任務,但在另一個線程上。 UI線程返回到窗口,因此沒有凍結。其全部內聯。 – Igor

+0

沒有冒犯性,我只是說你可以在'await'行後面加上'// Do continuation work.',因爲'async/await'會令人困惑。 – J3soon

3

WaitAll將阻止主線程。在所有任務完成後,請使用ContinueWhenAll並在那裏完成您的工作。

var link = txtSearchQuery.Text; 
for (var i = 1; i <= pageCount; i++) 
{ 

    tasks[i-1] = new Task(new Action(() => { Scrape(link, i); })); 
    tasks[i-1].Start(); 
} 

Task.Factory.ContinueWhenAll(tasks, completedTasks => 
{ 
// Do continuation work. 
}); 
+0

基本上像'js'一樣設置一個'callback'? – giannisf

+0

ContinueWhenAll還會在完成第一個參數中的所有任務後,以第二個參數中給出的Action開始一個任務。你可以認爲它是一個回調。 – Nitin