- PR -

Forms.Control継承型のファイナライゼーション

投稿者投稿内容
DSCH
常連さん
会議室デビュー日: 2005/10/23
投稿数: 24
投稿日時: 2007-01-06 10:38
囚人さん、Jittaさん、返答ありがとうございます。
リンク先を参考にさせていただきます。

ちなみにテストのためには以下のようなコードを書いていたので、
GCの対象となりFinalizeの呼び出しも起こりました。
コード:
            Form1 a = new Form1();
            a=null;
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();


「ウィンドウハンドルが関連付けられ」ているのは、
ShowメソッドでフォームをロードしてからCloseするまでですね。
yayadon
常連さん
会議室デビュー日: 2003/07/23
投稿数: 41
投稿日時: 2007-01-12 06:37
別スレッドから直接いじれないうんぬんの話はWindowと絡んでいて,

> 1.Finalizeメソッドの呼び出しはCLR内部の専用スレッドが行う。

専用スレッドは,(UIスレッドとは別スレッドなので)
UIスレッドが作成したWindowは,直接いじれないので,
dedicated finalizer thread側(CLR側)は,
SendMessageなどで命令をWindowに投げてやるわけです。
(BeginInvokeを使うのと似た理屈)

ただ,
対象のオブジェクトがロック状態/ビジー状態だと,
処理されなくて制御がもどってこなくなります。

で,しょうがないので,
.NET では,オブジェクトがロック状態でも,
優先度が上がっているスレッドからのものは優先して処理するようになっています。

で,
ファイナライズ専用のスレッドの priority を上げておくことによって
ブロックされないようにしているわけです。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-01-12 11:49
引用:

稍丼さんの書き込み (2007-01-12 06:37) より:

.NET では,オブジェクトがロック状態でも,
優先度が上がっているスレッドからのものは優先して処理するようになっています。

で,
ファイナライズ専用のスレッドの priority を上げておくことによって
ブロックされないようにしているわけです。


すみません、この辺りの情報が載っているところを教えていただけないでしょうか?

これは、lockなどでロックされている箇所でも、同じオブジェクトをロックする、
後から来た優先度の高いスレッドによって、割り込まれる可能性があるということ
でしょうか?
yayadon
常連さん
会議室デビュー日: 2003/07/23
投稿数: 41
投稿日時: 2007-01-12 14:59
一応
Threading Model
の部分の Reentrancy and Locking の箇所をよりどころにしています。

簡訳:

CLRのロック機能は,皆さんが予想するのとはちょっと違った振る舞いをします。
ロックを要求する時,スレッドは実行を完全に止めると思うでしょう。
実際は,そのスレッドは,high priorityメッセージを受け続け処理続けます。

で,以下に理由が続きます。

検証コードですが,これでOKなのかなぞですが,
コード:
using System;
using System.Threading;

public sealed class SomeType
{
    ~SomeType()
    {
        Console.WriteLine("SomeType is being finalized.");   
    }
}

public static class Program
{
    public static void Main()
    {
        SomeType st = new SomeType();

        Monitor.Enter(st);

        st = null;

        GC.Collect();
        GC.WaitForPendingFinalizers();

        Console.WriteLine("This is the last line.");
    }
}



で,

SomeType is being finalized.
This is the last line.

の順で出力されます。なので,ロックされていても,
ファイナライズされているんじゃないかと。

ただ,SomeType が,
スレの上の方で出てきたように Formを継承していて,
一度st.Show()したりすると,(st.Hide()しても)
そもそもGCの対象にならないようなので
素通りしてしまうんですけどね...(順番が逆になる)
yayadon
常連さん
会議室デビュー日: 2003/07/23
投稿数: 41
投稿日時: 2007-01-12 15:10
Main内の

Monitor.Enter(st);

がそもそも効いていないのでないか?という疑問は,例えば,

コード:
public sealed class SomeType
{
    ~SomeType()
    {
        Moniter.Enter(this); // これを追加
        Console.WriteLine("SomeType is being finalized.");   
    }
}



とすると,デッドロックを起こすので,Main側のロックは効いています。
yayadon
常連さん
会議室デビュー日: 2003/07/23
投稿数: 41
投稿日時: 2007-01-12 15:20
よく考えると,検証にはなってないか。
上の二つのコードは忘れてください。

[追記]
Finalize内でロックをかけれないというのは,
別スレッドがFinalizeを呼んでいるということで,
直接,finalizer thread が呼んでいるということですね。

やっぱり,
NativeWindow絡みでやらないとよくわからないということかな。
ただ,ファイナライザを呼び出せないんですよね。

[ メッセージ編集済み 編集者: 稍丼 編集日時 2007-01-12 16:24 ]
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-12 16:23
引用:

一応
Threading Model
の部分の Reentrancy and Locking の箇所をよりどころにしています。



これと Control 派生かどうかは関係ないような??
yayadon
常連さん
会議室デビュー日: 2003/07/23
投稿数: 41
投稿日時: 2007-01-12 17:09
下の方の理由のところで,

finalizeメソッドは,
UI thread からでなく,finalizer thread から呼ばれる。
STA で動いているCOMは,UI thread で作成されたので,
UI threadからしか破棄できない。
だから,CLRは,抜け道を用意した。

とあったので,同じように,
Window は,作成されたスレッドからしか破棄できない(できるのかな?)ので,
NativeWindowをもつControlクラスでも同じことがいえるのかな...
と勝手に思ったんですけどね。

なので,NativeWindowがウィンドウハンドルを握っている間は,
GCされないようなシカケを入れたのかなと。

[追記]
あらためて読み返してみると,抜け道の検証は,
UI thread がビジー状態の時の検証をしないといけませんでした。

[ メッセージ編集済み 編集者: 稍丼 編集日時 2007-01-12 17:22 ]

スキルアップ/キャリアアップ(JOB@IT)