何らかの理由で、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 でデリゲートを使用すると問題なく動作します。)