For some reason i have a hard time calling a delegate method from within a thread in Windows service. Don’t think environment makes that much of a difference, but want you to understand why i can’t just step through this code in debugger (trace-logging is quite possible though). Below is a simplified outline; all i want is to execute a callback from the main class to deal with received data (my desire is to separate data-processing implementation [involving too many other dependencies] from BaseSvc‘s library code):
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;
}
}
At first i thought smth is wrong with declaration or initialization of the delegate method, so various tries are marked with 1a, 1b, 1c and 2. However, in either scenario i end up with a trace printout confirming that if( fnProcCmd != null ) check passed, followed by a NullRefException. bData argument is initialized at that moment, 100% guaranteed and confirmed by tracing, so that leaves only fnProcCmd as the culprit. But it is initialized, is it not!? What am i missing here??
Could it be that the execution context for WinSvc class is different from that of BaseSvc, and/or that TcpComm( ) executes in its own thread? I’d expect a more intuitive error in that case..
I must be doing smth wrong. What should i do to enable such a callback?
UPDATE: After Henk’s suggestion i commented out ProcCmd‘s body and the problem disappeared, => issue is within that code and has nothing to do with the delegate mechanism. Sorry for confusion.
(BTW, using delegate via scenario 1a works fine.)
Looking at this part:
The null-checking on
fnProcCmdis extensive and convincing so it must be something happening insideProcCmd().To home in on the error, try it with an empty ProcCmd() :