C# 为什么只有在引发异常后才更新表单

C# 为什么只有在引发异常后才更新表单,c#,serial-port,xbee,C#,Serial Port,Xbee,我正在开发一个winform程序,该程序主要涉及Xbee和PC之间的COM端口通信。请允许我首先向您说明问题: 注: 不要担心委托函数,它只是检查返回的字节 这个程序以前可以运行,我今天刚刚添加了高速设置。所以 对于xbee设备,我必须从9600速度开始,然后更改为 我需要什么都行,38400。然而,一旦我将其设置为38400, 没有电源循环的xbee。下次连接设备时 ,速度保持在38400度。这就是我添加 尝试连接另一波特率的if(初始_失败)块 请遵循我用数字标记的注释 try

我正在开发一个winform程序,该程序主要涉及Xbee和PC之间的COM端口通信。请允许我首先向您说明问题:

注:

  • 不要担心委托函数,它只是检查返回的字节

  • 这个程序以前可以运行,我今天刚刚添加了高速设置。所以 对于xbee设备,我必须从9600速度开始,然后更改为 我需要什么都行,38400。然而,一旦我将其设置为38400, 没有电源循环的xbee。下次连接设备时 ,速度保持在38400度。这就是我添加 尝试连接另一波特率的if(初始_失败)块

  • 请遵循我用数字标记的注释

        try
        {
            portBuffer.Clear();
            myComPort.Write(myxbee.myxbee_cmd.cmd_mode, 0, myxbee.myxbee_cmd.cmd_mode.Length);   //RETURN OK <CR> 
    
            IAsyncResult res = d.BeginInvoke(null, null);
            if (res.IsCompleted == false)
            {
                res.AsyncWaitHandle.WaitOne(2000, false);
                if (res.IsCompleted == false)
                    initial_fail = 1; //1. start from here, once there is a timeout, set the initial_fail to 1, Time-out because the baudrate is not sync
                 if (d.EndInvoke(res) == false)
                   throw new Exception("Failing to enter the cmd mode");
            }
        }
        catch (ApplicationException e)
        {
            MessageBox.Show(e.Message);
            return false;
        }
        catch (Exception e)
        {
            MessageBox.Show("Error at step 1: {0}", e.Message);
            return false;
        }
        //2. here is the new code I added today
        if (initial_fail == 1)
        {
            myComPort.BaudRate = 38400; //3. Here I changed the speed and gui text
            cmbBaudRate.Text = "38400"; //PROBLEM: when Im doing step by step debug, seems like these two lines doesnt get executed. Winform GUI remain unchanged
            try
            {
    
                portBuffer.Clear();
                myxbee.command_buffer.Clear();
                dummy = "05";
                dummy_byte = Encoding.ASCII.GetBytes(dummy);
                myxbee.command_buffer.AddRange(myxbee.myxbee_cmd.data_rate); 
                myxbee.command_buffer.AddRange(dummy_byte);
                myxbee.command_buffer.Add(myxbee.myxbee_cmd.line_feed);
                myComPort.Write(myxbee.command_buffer.ToArray(), 0, myxbee.command_buffer.ToArray().Length);
                IAsyncResult res1 = d.BeginInvoke(null, null);
                if (res1.IsCompleted == false)
                {
                    res1.AsyncWaitHandle.WaitOne(1000, false);
                    if (res1.IsCompleted == false)
                        throw new ApplicationException("Timeout"); 
                        //4. since the winform hasnt shown any bd_rate change, the program will throw a time-out here again 
                }
                if (d.EndInvoke(res1) == false)
                    throw new Exception("Fail in setting data rate to 38400");
                chkHighSpeed.Checked = true;
                high_speed_set = 1;
                MessageBox.Show("Xbee high speed");
            }
            catch (ApplicationException e)
            {
                MessageBox.Show(e.Message);
                return false;
                //5. BUT AFTER THIS TIMEOUT message, the winform's GUI will be updated to 38400, and rerun the whole test will pass
            }
    
    试试看
    {
    portBuffer.Clear();
    myimport.Write(myxbee.myxbee_cmd.cmd_mode,0,myxbee.myxbee_cmd.cmd_mode.Length);//返回OK
    IAsyncResult res=d.BeginInvoke(null,null);
    如果(res.IsCompleted==false)
    {
    res.AsyncWaitHandle.WaitOne(2000,false);
    如果(res.IsCompleted==false)
    initial_fail=1;//1。从这里开始,一旦出现超时,将initial_fail设置为1,超时,因为波特率不同步
    如果(d.EndInvoke(res)=false)
    抛出新异常(“未能进入cmd模式”);
    }
    }
    捕获(ApplicationException e)
    {
    MessageBox.Show(e.Message);
    返回false;
    }
    捕获(例外e)
    {
    Show(“步骤1的错误:{0}”,e.Message);
    返回false;
    }
    //2. 这是我今天添加的新代码
    如果(初始故障==1)
    {
    myimport.BaudRate=38400;//3。这里我更改了速度和gui文本
    CMBAudrate.Text=“38400”//问题:当我进行逐步调试时,这两行代码似乎没有执行。Winform GUI保持不变
    尝试
    {
    portBuffer.Clear();
    myxbee.command_buffer.Clear();
    dummy=“05”;
    伪字节=Encoding.ASCII.GetBytes(伪);
    myxbee.command\u buffer.AddRange(myxbee.myxbee\u cmd.data\u rate);
    myxbee.command\u buffer.AddRange(伪字节);
    myxbee.command\u buffer.Add(myxbee.myxbee\u cmd.line\u提要);
    myimport.Write(myxbee.command\u buffer.ToArray(),0,myxbee.command\u buffer.ToArray().Length);
    IAsyncResult res1=d.BeginInvoke(null,null);
    如果(res1.IsCompleted==false)
    {
    res1.AsyncWaitHandle.WaitOne(1000,false);
    如果(res1.IsCompleted==false)
    抛出新的ApplicationException(“超时”);
    //4.由于winform没有显示任何bd_速率变化,程序将再次在此处抛出超时
    }
    if(d.EndInvoke(res1)==false)
    抛出新异常(“未能将数据速率设置为38400”);
    chkHighSpeed.Checked=true;
    高速组=1;
    MessageBox.Show(“Xbee高速”);
    }
    捕获(ApplicationException e)
    {
    MessageBox.Show(e.Message);
    返回false;
    //5.但在此超时消息之后,winform的GUI将更新为38400,重新运行整个测试将通过
    }
    
  • 这是GUI的一部分,看起来像:


    所以我的问题是,为什么只有在超时异常之后,波特率才会被更新?

    这个问题来自这样一个事实,即您的进程与ui在同一个线程上。 所以UI可以被com进程冻结。 您可以使用doevents方法更新UI来解决您的问题,但在您的情况下,这不是最好的方法。
    使用后台Worker在另一个线程上启动com进程。

    这里是backgroundworker示例的url