53

メソッドに次のコードブロックがある場合(.NET 4とタスク並列ライブラリを使用):

var task = new Task(() => DoSomethingLongRunning());
task.Start();

メソッドが返されると、そのタスクはスコープ外になり、ガベージコレクションされるのでしょうか、それとも完了するまで実行されるのでしょうか。GCingの問題には気づいていませんが、GCで競合状態に陥っていないことを確認したいと思います。

4

2 に答える 2

36

アップデート:

この質問に答えた後 (ずっと前に!)、Tasks が常に完了まで実行されるというのは正しくないことがわかりました。たとえば、タスクが完了しない可能性がある小さな、たとえば「コーナー」ケースがあります。

その理由は次のとおりです。以前に回答したように、タスクは本質的にスレッドです。しかし、それらはバックグラウンドスレッドです。すべてのフォアグラウンド スレッドが終了すると、バックグラウンド スレッドは自動的に中止されます。そのため、タスクに対して何もせずにプログラムが終了した場合、タスクが完了しない可能性があります。

常にタスクを待機する必要があります。詳細については、Jon がくれた優れた回答を参照してください。


オリジナル:

タスクは ThreadPool にスケジュールされます。つまり、それらは本質的にスレッドです¹ (実際には、スレッドをカプセル化します)。

スレッドのドキュメントから:

スレッドを開始したら、Thread オブジェクトへの参照を保持する必要はありません。スレッドは、スレッド プロシージャが完了するまで実行を続けます。

したがって、いいえ、それへの参照を保持する必要はありません。

また、ドキュメントには、タスクを作成するための推奨される方法は、そのファクトリを使用することであると記載されています。

StartNew メソッドを使用して、1 回の操作でタスクを作成および開始することもできます。これは、作成とスケジューリングを分離する必要がない場合、タスクを作成して開始するための推奨される方法です (...)

それが役に立てば幸い。


¹ドキュメントによると:

タスクは非同期操作を表し、ある意味では新しいスレッドまたは ThreadPool 作業項目の作成に似ていますが、抽象化のレベルが高くなります。

于 2010-05-06T17:11:32.120 に答える
16

タスクは完了するまで実行されます。他に参照がない場合でも(ルート化されていないという用語だと思います)、スレッドプールはそれへの参照を保持し、少なくともガベージコレクションされないようにします(少なくとも、完了後、完了するまでガベージコレクションされる保証はありません。

于 2010-05-06T16:47:03.847 に答える