2016-03-24 18 views
-1

私はページング結果でサイトを擦るサイトスクレーパーを持っています。WaitAllブロックのブロック

すべてのページについて、私はそれをより速くするためにタスクを実行しようとしますが、フリーズします。

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"); 

私は間違っていますか?私はあなたが非同期をサポートしています.NETの最新バージョンを/使用していると仮定しています

+0

「WaitAll」はブロック動作です。タスクは並行して実行されるかもしれませんが、最長の実行中のタスクが完了するのを待っている間、 'WaitAll'はブロックされます。 –

+0

*私は間違って何をしていますか?*すべてのタスクが完了するまで待っています*。これにより、現在の(UI)スレッドがブロックされます。 –

+0

あなたはwpfアプリケーションを持っています、なぜあなたは 'async' /' await'を使っていませんか? – kai

答えて

5

はそれを非同期にするために

変更あなたのメソッドのシグネチャを待つとTask.WhenAllを使用して、タスクの結果を待っています。これは、UIスレッドieを解放します。 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

「async/await」は混乱する可能性があるので、 'await'行の後に' // Do continuation work .'のようなものを置くことができます。 – 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はまた、第1引数のすべてのタスクが完了した後に第2引数で指定されたアクションでタスクを開始します。あなたはコールバックとしてそれを考えることができます。 – Nitin