2

次のコードを検討してください。

public class ChainHandler
{
    public void ProcessTopUp(string amount, string phone, ResponseCallback responseCallback)
    {
        var statebag = GetStateBag();

        ICommand basecommand = new BlmLoginCommand(statebag);
        basecommand .SetNext(new BlmDynamicCommand(statebag, RequestMessageEvent.TCD_RecargaTAE10, new Dictionary<string, string> { { "amt", amount }, { "cel", phone } }))
               .SetNext(new BlmDynamicCommand(statebag, RequestMessageEvent.TCD_BuyProduct))
               .SetNext(new BlmEndCommand(statebag, responseCallback));

        basecommand.ExecuteAsync();
    }


}

class Program
{
    static void Main(string[] args)
    {
        ChainHandler ch = new ChainHandler();

        ch.ProcessTopUp("5.00", "0123456789", OnProcessResponse);

        Console.ReadLine();
    }

    private static void OnProcessResponse()
    {
        //...
    }
}

メソッド「ExecuteAsync」は、コマンドを使用する非同期フローを開始します。内部で Socket クラスを非同期に使用するコマンド (イベント ベースの非同期パターン)。

問題は、「ExecuteAsync」メソッドを離れた後にオブジェクト basecommand が破棄されるため、EndCommand に到達しない可能性はありますか?

.net でさえ、EndCommand にコールバック メソッドがあることを知っていますか?

それとも、.net は、非同期フローが終了するまでオブジェクトを存続させるのに十分なほどインテリジェントですか?

オブジェクトが存続しない場合、ガベージ コレクターに basecommand を破棄しないように指示するにはどうすればよいですか?

4

2 に答える 2

3

ここでは正確さが重要です。オブジェクトは自動的に破棄されません。これは常に、usingステートメントまたは Dispose() メソッドの呼び出しによって、コード内で明示的に行われます。したがって、コードで破棄しなくても問題はありません。

おそらくあなたが言いたかったのは、「ガベージコレクション」でした。ガベージ コレクターがオブジェクトへの参照を認識でき、その参照がそれ自体が生きている別のオブジェクトによって保持されている限り、これは .NET では非常に単純です。オブジェクトは収集されません。

ただし、常に明確であるとは限りませんが、その参照がどこに保存されているかです。C# コンパイラは、コードを書き換えて、クラス内のメソッドから隠しクラスのメソッドに移動できます。その隠しクラスには、言葉では言い表せない名前があり、参照を格納するフィールドがあります。ガベージ コレクターが確認できるため、オブジェクトが収集されなくなります。コードから非表示のクラス オブジェクトのフィールドに参照をコピーするための専門用語は、「変数のキャプチャ」です。

このコード書き換えのトリックは、C# の多くの場所で使用されています。元々、匿名メソッドとイテレータをサポートするために言語に実装されていました。その後のバージョンでは、ラムダ式と非同期メソッドを実装するように拡張されています。何が起こっているかを確認する良い方法は、C# コンパイラが生成するコードを見ることです。ildasm.exe または不完全な逆コンパイラで表示されます。そうでなければ、これは確かに「十分にインテリジェント」というモニカに適合します。

于 2013-05-30T10:49:07.717 に答える
1

あなたの場合、デリゲート/コールバック参照があるため、コマンドは破棄されません。これは、デリゲートが存続している限り、コマンド オブジェクトがデリゲートによって存続することを意味します。最終的に、コールバックが実行されると、GC はそのまま (ルートを持たないオブジェクト) を選択し、それに応じて破棄します。

更新しました:

他のシナリオは、コールバック参照がない場合です。

このような場合、EPM (コード内で従うパターン) API がスレッド プール (具体的には IO 完了スレッド) 内でリクエストへの参照を保持するため、オブジェクトはガベージ コレクションの対象とはなりません。このヒントは、GC が完了するまで触れたり収集したりしないようにします。

于 2013-05-30T09:00:45.923 に答える