19

次のようなコードがあるとします。

int Main()
{
    if (true)
    {
       new Thread(()=>
          {
              doSomeLengthyOperation();
          }).Start();
    }
    while (true)
    {
       //do nothing
    }
}

2つのスレッドがあります。メインスレッドをMain()関数を実行しているスレッドと呼び、「if」テスト内でスレッドAとして新しく作成されたスレッドを呼び出します。

私の質問は、スレッドAはいつ破壊されるのですか?doSomeLenghtyOperation()は完了まで実行できますか?

スレッドAを指す参照がないため、ガベージコレクションの候補としてマークされますか?

  1. 「newThread()。Start()」ステートメント自体が終了した直後?
  2. 「if(true)」スコープが終了した直後?
  3. doSomeLengthOperation()が実行されて終了した後?
  4. 一度もない?

私が見るすべての例は、参照を保持しているMain()と、終了する前にスレッドAとの結合を待機しているメインスレッドです。上記のコードの存続期間が何であるか興味があります。

前もって感謝します!

4

4 に答える 4

14

「スレッド」という言葉は、ここでいくつかのことを意味する可能性があります。

  • System.Threading.Thread オブジェクト (によって作成new Thread())、
  • CLR スレッド (マネージド スレッド)、
  • OS スレッド (アンマネージド スレッド)。

スレッド オブジェクトへの参照がなくなるため、Start() メソッドが完了するとすぐにスレッド オブジェクトが GC の候補になります。

doSomeLengthyOperation() の実行中、マネージド スレッドは存続します。

Microsoft MVP の James Kovacsの記事を引用します。

マネージド スレッドの有効期間は、それを作成した Thread オブジェクトとは無関係です。関連する Thread オブジェクトへのすべての参照を失ったという理由だけで、まだ作業を行っているスレッドを GC で終了させたくない場合は、これは非常に良いことです。したがって、GC は Thread オブジェクトを収集していますが、実際のマネージド スレッドは収集していません。

この記事には、自分で試してみたい場合に役立つコード サンプルも含まれています。

オペレーティング システムのスレッドは、理論的にはマネージド スレッドと 1 対 1 の関係はありません。MSDNから:

...高度なホストは、CLR ホスティング API を使用して、同じオペレーティング システム スレッドに対して多数のマネージド スレッドをスケジュールしたり、異なるオペレーティング システム スレッド間でマネージド スレッドを移動したりできます。

ただし、実際には、CLR スレッドは今日の Windows スレッドに直接マップされます

于 2010-09-14T08:20:47.440 に答える
14

Threadオブジェクトは、使用されなくなるとすぐに、つまりStartメソッドを呼び出した直後にガベージ コレクションの対象になります。(ただし、ガベージ コレクターは特定の時間に実行されるため、すぐには収集されません。)

ただし、実際のスレッドはオブジェクトに依存しておらず、オブジェクトが収集されThreadても実行を続けます。Thread

メイン メソッドの終了時にスレッドがまだ実行されている場合、スレッドをバックグラウンド スレッドとしてマークしていない限り、アプリケーションはスレッドが完了するまで終了しません。

于 2010-09-13T09:36:14.340 に答える
10

スレッド A はいつ破棄されますか?

終わったらdoSomeLengthyOperation

doSomeLenghtyOperation() は完了まで実行できますか

バックグラウンド スレッドではないため、メイン スレッドが存在する場合でも、はい。メイン スレッドが存在する場合は常に、スレッドを開始する前にIsBackgroundプロパティをに設定trueすると、このスレッドも停止します。

于 2010-09-13T09:37:30.657 に答える
0

これは素晴らしい質問です!スレッドは確実に終了し、自分で試すことができます。しかし、その間に GC.Collect() を呼び出すと、面白くなる可能性があります。Richter の C# via CLR によると、ガベージ コレクションされます。

アップデート

Thread.CurrentThread は参照を持つことでメモリに保持されるため、ガベージ コレクションにはならないと思います。

于 2010-09-13T09:36:45.123 に答える