delegate.Invoke和delegate.BeginInvoke - 在同一方法上使用,返回两个不同的结果

时间:2011-10-12 14:00:09

标签: c# asynchronous delegates timer

我正在编写一个通过串口与4个设备通信的软件。其中之一,输入/输出模块(ICP CON)具有4个输入通道(DL)和4个输出通道(RL)。我需要监控DL通道的状态,然后,当检测到信号时,我必须进行一些处理,这取决于检测到的信号。

我以异步方式调用4个方法,每500ms(定时器),这是tick事件:

//stop the timer
timer1.Stop();

//open com port 2
Tester.Devices.ICP.OpenICPPort(2, 9600);

//dl 0
ic = new CheckDLStatus(0, this);
ic.Execute();

//dl 1
ic = new CheckDLStatus(1, this);
ic.Execute();

//dl 2
ic = new CheckDLStatus(2, this);
ic.Execute();

//dl3 
ic = new CheckDLStatus(3, this);
ic.Execute();

//close com port 2
Tester.Devices.ICP.CloseICPPort(2);

//enable the timer again
timer1.Enabled = true;

public CheckDLStatus(int DL, Form1 F1)
{
    //form 1 instance
    f1 = F1;

    // setup the delegate to call
    switch (DL)
    {
        case (0):
        {
            checkDL_delegate = new checkDL(
                BusinessLogicLayer.Classes.
                DevicesCommunication.CheckDl0);

            break;
        }
        case (1):
        {
            checkDL_delegate = new checkDL(
                BusinessLogicLayer.Classes.
                DevicesCommunication.CheckDl1);

                break;
        }
        case (2):
        {
            checkDL_delegate = new checkDL(
                BusinessLogicLayer.Classes.
                DevicesCommunication.CheckDl2);

                break;
        }
        case (3):
        {
            checkDL_delegate = new checkDL(
                BusinessLogicLayer.Classes.
                DevicesCommunication.CheckDl3);

                break;
        }
    }
}


public static void CheckDl2()
{
    //declare
    bool currentStatus;

    try
    {
        //input
        currentStatus = DevicesCommunication.Dl_2_On; 
        //should be false at the start of the test, 
        //so when it becomes true, the change is detected immediately

        //dl2?
        if (ICP.LookForSignal_DL2((short)2, 
            Util.Classes.Util.ResolveComPortNumber(
                Cache.settings.icpModulePort),     
            Convert.ToInt32(Cache.settings.icpModuleBaudRate)))
        {
            //signal detected
            DevicesCommunication.Dl_2_On = true;
        }
        else
        {
            //signal not detected
            DevicesCommunication.Dl_2_On = false;
        }

        //check, if status of DL2 has been changed 
        //(from true to false, from false to true)
        if (currentStatus != DevicesCommunication.Dl_2_On)
        {
            //status from before checking signal is different
            // from status read from the device so
            //status has changed

            if (DevicesCommunication.Dl_2_On)
            {
                DevicesCommunication.DL2_apperancesCounter += 1;

                //TODO
                //process
                //ProcessDL2();
            }
        }
        else
        {
            //status did not change
            //just clear buffer
            ClearBuffer();
        }

        return;
    }
    catch (Exception ex)
    {
        Util.Classes.ErrorLogging.LogError(ex, true);
        //EndCurrentTest(); 
        return;
    }
}

Execute()方法,用于调用委托:

public void Execute()
{
    // call the method on the thread pool
    checkDL_delegate.BeginInvoke(
        this.CallBack, null);

    //checkDL_delegate.Invoke();
}

检查DL2状态的方法:

public static bool LookForSignal_DL2(short DL_number, int port, int baudRate)
{
    //declare
    bool iBit;

    try
    {
        //check if there is a signal at specified Dl_number
        iBit = DCON.Read_DI_Bit(Convert.ToByte(port), 1, -1, 
            DL_number, 16, 0, 100);

        //return resposne
        return iBit; //true/false
    }
    catch (Exception ex)
    {
        Util.Classes.ErrorLogging.LogError(ex, true);
        return false;
    }
}

我的问题是,当我打开DL2频道上的信号时,我就像这样调用LookForSignal_DL2,没有定时器和异步调用(仅用于测试):

private void button25_Click(object sender, EventArgs e)
{
    ICP.OpenICPPort(2, 9600);

    if (ICP.LookForSignal_DL2(2, 2, 9600))
    {
        MessageBox.Show("True");
    }
    else
    {
        MessageBox.Show("false!");
    }

    ICP.CloseICPPort(2);
}

它有效 - 返回true。

如果在Execute()方法中我使用Invoke,这使方法调用同步 - 它可以工作(返回true),但这样我当时只能检查1个信号。

如果在Execute()方法中我使用BeginInvoke它不起作用,则返回false,即使DL2中有信号。

我承认我不知道发生了什么。你有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我想通了,如果它对任何人有帮助,我在这里犯了一个错误(粗体文字):

//stop the timer
timer1.Stop();

//open com port 2
Tester.Devices.ICP.OpenICPPort(2, 9600);

//dl 0
ic = new CheckDLStatus(0, this);
ic.Execute();

//dl 1
ic = new CheckDLStatus(1, this);
ic.Execute();

//dl 2
ic = new CheckDLStatus(2, this);
ic.Execute();

//dl3 
ic = new CheckDLStatus(3, this);
ic.Execute();

<强> Tester.Devices.ICP.CloseICPPort(2);

我异步运行我的方法,但是代码的执行继续进行,每次端口关闭之前,任何方法都能检查信号。不幸的是,SDK库在这种情况下不会返回任何错误,所以它只是保持返回false。

感谢您的评论。