调用初始化的(非null)委托会产生NullReferenceException(在Windows服务中)
本文关键字:NullReferenceException Windows 服务 初始化 null 调用 | 更新日期: 2024-09-23 08:52:13
由于某些原因,我很难从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;
}
}
起初,我认为smth对委托方法的声明或初始化是错误的,所以各种尝试都用1a、1b、1c和2标记。然而,在任何一种情况下,我都会得到一个跟踪打印输出,确认if( fnProcCmd != null )
检查通过,然后是NullRefExceptionbData参数在那一刻被初始化,通过跟踪100%保证和确认,因此只留下fnProcCmd
作为罪魁祸首。但是它已经初始化了,不是吗!?我在这里错过了什么??
是否可能是WinSvc类的执行上下文与BaseSvc的执行上下文不同,和/或TcpComm( )
在自己的线程中执行?我希望在这种情况下会出现更直观的错误。。
我一定做错了。我应该怎么做才能启用这样的回调?
UPDATE:在Henk的建议之后,我注释掉了ProcCmd
的主体,问题消失了,=>问题在该代码中,与委托机制无关。抱歉弄糊涂了
(顺便说一句,通过场景1a使用委托很好。)
查看此部分:
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;
}