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 )检查通过,然后是空引用异常。 bData参数在那一刻被初始化,100% 保证并通过跟踪确认,因此仅留下fnProcCmd作为罪魁祸首。但它被初始化了,不是吗!?我在这里想念什么?

可能是WinSvc类的执行上下文与BaseSvc的执行上下文不同,和/或TcpComm( )在它自己的线程中执行?在这种情况下,我希望出现更直观的错误..

我一定做错了。我应该怎么做才能启用这样的回调?

更新:在 Henk 的建议之后,我注释掉了ProcCmd's body 并且问题消失了,=> 问题在该代码中,与委托机制无关。很抱歉造成混乱。
(顺便说一句,通过场景 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 回答