17

一緒に楽しんでいますSystem.Threading.Tasks。私が見るコードサンプルの多くは、しかし、そのように見える:

Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork())
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning)
Task.WaitAll(lcTask, lcTaskLong)

それがサンプルの範囲です。

タスクが実装IDisposableそれで、明らかに私はそれらを処分することになっています、しかし、もし私がただ「消し去りたい」としたらどうでしょうか?

処分しない場合、スレッド/ハンドル/メモリ/カルマをリークしますか? 私はタスクを「間違って」使っていますか? (デリゲートを使用してタスクをそのままにしておくべきですか?)

に処分できますかContinueWith()? (ロシアンルーレットを弾いているようです。)

1 답변


18

通常の経験則では、常に電話をかけることです。Dispose()すべての上IDisposable実装TaskそしてTask<T>多くの場合、ファイナライザにこの処理を任せることをお勧めします。

タスクが実装する理由IDisposableこれは主に内部のWaitHandleによるものです。これは、タスクの継続が正しく機能するために必要であり、タスクに継続がある場合にのみ使用されます。継続がない場合、TaskのDisposeメソッドは実際には効果がありません - したがって、この場合は必須ではありません。

とはいえ、タスク継続があるほとんどの場合、Dispose()を適切に呼び出すことができるような方法でコードを記述することは非常に困難です。 Task呼び出しは通常非同期であるため、ステートメントの使用は通常Taskインスタンスでは機能しません。特にusingステートメントを使用している場合は、タスクを非常に早く処理することは非常に簡単です。

あなたの場合、Taskへの参照を保持してそれに対してDispose()を正しく呼び出すのが比較的簡単であれば、私はそうするでしょう。しかし、これによってロジックがはるかに複雑になる場合は、通常、タスクはそうではないと思います。IDisposableそして、タスクのファイナライザでクリーンアップできるようにします。

詳細については、私はお勧めしますMSDNフォーラムでこのスレッドを読むStephen Toubが、TaskがIDisposableを実装する理由を詳しく説明し、上記の私の提案と同様のガイダンスを提供しています。


  • そして、... [CodeAnalysis.SuppressMessage( "Microsoft.Reliability"、 "CA2000"、Justification = ";stackoverflow.com/questions/5985973/… - GarethOwen
  • あなたがリンクしているStephen Toubスレッドから判断すると、「[wait handle]はタスク継続を適切に機能させるために必要であり、タスクに継続がある場合にのみ使用される」と言ったときに逆方向に持っています継続がない場合、TaskのDisposeメソッドは実際には効果がありません... "しかし、Toub氏によると、Taskがイベントハンドルをラップしている可能性があるため、Task.Disposeが存在します。継続を使用するだけでは、そのイベントハンドルは割り当てられず、Disposeの値は大幅に減少します。 "すなわち、あなたが上で暗示していることの逆です。 - Daniel Earwicker

リンクされた質問


関連する質問

最近の質問