回答編集履歴

3

Timer が発動する前に GC が走ると を追加

2022/06/27 09:00

投稿

KOZ6.0
KOZ6.0

スコア2628

test CHANGED
@@ -9,7 +9,7 @@
9
9
  メソッド実行中は、解放対象にはなりません。
10
10
 
11
11
  ただし、SubClass が Timer のインスタンスを保持していないので、危ういコードになっています。
12
- 次のように SubClass のインスタンスを参照していても、Timer のインスタンスが解放され、TimerCallback が呼ばれません。
12
+ 次のように SubClass のインスタンスを参照していても、Timer が発動する前に GC が走ると Timer のインスタンスが解放され、TimerCallback が呼ばれません。
13
13
 
14
14
  ```C#
15
15
  using System;

2

大幅に書き換え

2022/06/27 08:56

投稿

KOZ6.0
KOZ6.0

スコア2628

test CHANGED
@@ -1,8 +1,15 @@
1
+ 「サブクラスで処理している途中に」というのが「TimerCallback を実行中」というのであれば、1,2,3 の回答は「解放されない」ということになります。
2
+
3
+ 「ガベージ コレクションの基礎」
4
+ [https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals](https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals)
5
+ の「メモリの解放」のところに
6
+ 「アプリケーションのルートには、静的フィールド、スレッドのスタック上のローカル変数、CPU レジスタ、GC ハンドル、ファイナライズ キューが含まれています。」
1
- ■ 質問1につ
7
+ う記述があります。
8
+
9
+ メソッド実行中は、解放対象にはなりません。
10
+
2
- SubClass が Timer のインスタンスを保持していないので、危ういコードになっています。
11
+ ただし、SubClass が Timer のインスタンスを保持していないので、危ういコードになっています。
3
- 次のコードを実行してみてください。
4
- TimerCallback が呼ばれることなくデストラクタが実行されるのが確認できます。
5
- GC を2回実行していますが1回目で Timer のインスタンスが回収され、2回目で SubClass の回収行われま
12
+ 次のように SubClass のインスタンス参照していても、Timer のインスタンスが解放され、TimerCallback呼ばれません
6
13
 
7
14
  ```C#
8
15
  using System;
@@ -11,9 +18,7 @@
11
18
  class Program
12
19
  {
13
20
  static void Main(string[] args) {
14
- new SubClass();
21
+ var s = new SubClass();
15
- GC.Collect();
16
- GC.WaitForPendingFinalizers();
17
22
  GC.Collect();
18
23
  GC.WaitForPendingFinalizers();
19
24
  Console.WriteLine("何かキーを押してください。");
@@ -30,17 +35,13 @@
30
35
  private void TimerCallback(object obj) {
31
36
  Console.WriteLine("TimerCallback");
32
37
  }
33
-
34
- ~SubClass() {
35
- Console.WriteLine("Finalize");
36
- }
37
38
  }
38
39
  ```
39
40
 
40
41
  下のように Timer のインスタンスを保持すれば TimerCallback は実行されます。
41
42
  IDE0052 の警告が出るので抑止してください。
42
43
 
43
- ```
44
+ ```C#
44
45
  class SubClass
45
46
  {
46
47
  #pragma warning disable IDE0052
@@ -52,12 +53,3 @@
52
53
  }
53
54
  ```
54
55
 
55
- ■質問2,3について
56
- 両方とも、TimerCallback を実行中にGCが起きると、外部から参照されなくなった SubClass はどうなるか?という質問かと思います。
57
- 「ガベージ コレクションの基礎」
58
- [https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals](https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals)
59
- の「メモリの解放」のところに
60
- 「アプリケーションのルートには、静的フィールド、スレッドのスタック上のローカル変数、CPU レジスタ、GC ハンドル、ファイナライズ キューが含まれています。」
61
- という記述があります。
62
- つまり、メソッドが実行されている場合、そのインスタンスは回収対象外ということになろうかと思います。
63
-

1

質問2、3について回答

2022/06/27 06:16

投稿

KOZ6.0
KOZ6.0

スコア2628

test CHANGED
@@ -1,6 +1,8 @@
1
+ ■ 質問1について
1
2
  SubClass が Timer のインスタンスを保持していないので、危ういコードになっています。
2
3
  次のコードを実行してみてください。
3
4
  TimerCallback が呼ばれることなくデストラクタが実行されるのが確認できます。
5
+ GC を2回実行していますが、1回目で Timer のインスタンスが回収され、2回目で SubClass の回収が行われます。
4
6
 
5
7
  ```C#
6
8
  using System;
@@ -49,3 +51,13 @@
49
51
  timer = new Timer(TimerCallback, null, 5 * 1000, Timeout.Infinite);
50
52
  }
51
53
  ```
54
+
55
+ ■質問2,3について
56
+ 両方とも、TimerCallback を実行中にGCが起きると、外部から参照されなくなった SubClass はどうなるか?という質問かと思います。
57
+ 「ガベージ コレクションの基礎」
58
+ [https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals](https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals)
59
+ の「メモリの解放」のところに
60
+ 「アプリケーションのルートには、静的フィールド、スレッドのスタック上のローカル変数、CPU レジスタ、GC ハンドル、ファイナライズ キューが含まれています。」
61
+ という記述があります。
62
+ つまり、メソッドが実行されている場合、そのインスタンスは回収対象外ということになろうかと思います。
63
+