出于某种原因,我很难从 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 )
检查通过,然后是空引用异常。 bData参数在那一刻被初始化,100% 保证并通过跟踪确认,因此仅留下fnProcCmd
作为罪魁祸首。但它被初始化了,不是吗!?我在这里想念什么?
可能是WinSvc类的执行上下文与BaseSvc的执行上下文不同,和/或TcpComm( )
在它自己的线程中执行?在这种情况下,我希望出现更直观的错误..
我一定做错了。我应该怎么做才能启用这样的回调?
更新:在 Henk 的建议之后,我注释掉了ProcCmd
's body 并且问题消失了,=> 问题在该代码中,与委托机制无关。很抱歉造成混乱。
(顺便说一句,通过场景 1a 使用委托可以正常工作。)