1

何らかの理由で、Windows サービスのスレッド内からデリゲート メソッドを呼び出すのに苦労しています。環境がそれほど大きな違いを生むとは思わないでください。ただし、デバッガーでこのコードをステップ実行できない理由を理解してほしいです (ただし、トレース ロギングは可能です)。以下は簡単な概要です。私が望むのは、受信したデータを処理するためにメインクラスからコールバックを実行することだけです (私の望みは、データ処理の実装 [他の依存関係が多すぎる] をBaseSvcのライブラリコードから分離することです):

public class    BaseSvc         // library class (separate DLL)
{
    public delegate     bool    dlProcCmd( byte[] bData );
    public static   dlProcCmd   fnProcCmd;

    public static void      Start( )                                // 1
//  public static void      Start( BaseSvc.dlProcCmd ProcCmd )      // 2
    {
//      BaseSvc.fnProcCmd=  ProcCmd;                                // 2
        ..
        bListen=    true;
        thTcpComm=  new Thread( new ThreadStart( TcpComm ) );
        thTcpComm.Start( );
    }
    ..
    public static void      TcpComm( )
    {
        ..
        while(  bListen  )
        {
            ..
            if(  fnProcCmd != null  )
            {
                Utils.Log( fnProcCmd.Method.ToString( ) );
                    // prints:Boolean ProcCmd(Byte[])
                fnProcCmd( bData );     // throws:
                    // Void TcpComm():  System.NullReferenceException
                    // Object reference not set to an instance of an object.
            }
        }
    }
    ..
}

..

public partial class    WinSvc : ServiceBase        // SCM-compatible .exe
{
    /// <summary>Handles Start command</summary>
    protected override void     OnStart( string[] args )
    {
        BaseSvc.fnProcCmd=  ProcCmd;                                // 1a
//      BaseSvc.fnProcCmd=  new BaseSvc.dlProcCmd( ProcCmd );       // 1b
//      BaseSvc.fnProcCmd+= new BaseSvc.dlProcCmd( ProcCmd );       // 1c
        BaseSvc.Start( );                                           // 1
//      BaseSvc.Start( new BaseSvc.dlProcCmd( ProcCmd ) );          // 2
        ..
    }

    public bool     ProcCmd( byte[] bData )
    {
        ..
        return  true;
    }
}

最初は、デリゲート メソッドの宣言または初期化が間違っていると思ったので、さまざまな試行が 1a、1b、1c、および 2 でマークされていますif( fnProcCmd != null )。 NullRefException. bData引数はその時点で初期化され、100% 保証され、トレースによって確認されるためfnProcCmd、犯人としてのみ残されます。でも初期化されてるじゃないですか!? ここで何が欠けていますか??

WinSvcクラスの実行コンテキストがBaseSvcの実行コンテキストと異なる、および/またはTcpComm( )独自のスレッドで実行される可能性がありますか? その場合、より直感的なエラーが予想されます..

私は間違ったことをしているに違いない。このようなコールバックを有効にするにはどうすればよいですか?

更新: Henk の提案の後、私は の体をコメントアウトしProcCmd、問題は消えました。=> 問題はそのコード内にあり、デリゲートメカニズムとは何の関係もありません。混乱させて申し訳ありません。
(ところで、シナリオ 1a でデリゲートを使用すると問題なく動作します。)

4

1 に答える 1

1

この部分を見ると:

        if(  fnProcCmd != null  )
        {
            Utils.Log( fnProcCmd.Method.ToString( ) );
                // prints:Boolean ProcCmd(Byte[])
            fnProcCmd( bData );     // throws:
                // Void TcpComm():  System.NullReferenceException
                // Object reference not set to an instance of an object.
        }

のヌルチェックfnProcCmdは広範で説得力があるため、内部で何かが起こっているに違いありませんProcCmd()

エラーを確認するには、空の ProcCmd() で試してください。

 public bool     ProcCmd( byte[] bData )
 {
    //    ...
    //
    //    ...
    return  true;
 }
于 2012-08-03T09:26:56.240 に答える