串口试图连接时C#UI冻结

时间:2013-03-26 11:25:27

标签: c# wpf dispatchertimer

我有一个问题,关于为什么我的C#接口在串行端口连接期间冻结。如果我连接到有效的串行端口(我的设备发送我期望的字节数),接口不会冻结。但是,如果用户尝试连接到计算机上的另一个端口或设备的错误型号,则程序在发送“?”时不会返回任何数据。字符等第一行:message [i] =(byte)port.BaseStream.ReadByte();导致超时并落入我的捕获并尝试连接3次然后警告用户失败的连接。在三次尝试完成后,UI工作正常,但是当他们正在进行时,UI没有响应。有任何想法吗?在此先感谢,下面是我的代码。

public void windowLoop(object sender, EventArgs e)
    {
        if (Global.connecting)
        {
            try
            {
                if (i == 0) { port.BaseStream.Flush(); port.BaseStream.WriteByte(63); }
                message[i] = (byte)port.BaseStream.ReadByte();
                if (i == 6)
                {
                    connectAttempts = 1;
                    i = 0;
                    String result = Encoding.ASCII.GetString(message);
                    if (result == "ASUTTON")
                    {
                        //connection succeeded
                        Global.connecting = false;
                        Global.receiving = true;
                        setDisplay(2);
                    }
                    else
                    {
                        //connection failed
                        Global.connecting = false;
                        disconnect();
                        MessageBox.Show(radio, "You are not connection to an Agent (Radio Version)", "Connection Failed", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                }
                else
                {
                    i++;
                }
            }
            catch
            {
                if (connectAttempts >= connectAttemptsLimit)
                {
                    connectAttempts = 1;
                    Global.connecting = false;
                    disconnect();
                    MessageBox.Show(radio, "Your device failed to connect to the program.", "Connection Failed", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                else
                {
                   connectAttempts++;
                }
            }
        }
        else if (Global.sending)
        {

上面是我的代码,它通过设置为每10毫秒运行一次的DispatcherTimer对象连续运行。

4 个答案:

答案 0 :(得分:2)

为了使应用程序保持响应,建议使用线程。与串行端口的通信是一个阻塞调用,它等待超时才能确定端口不工作。

理想的解决方案是使用后台工作程序组件,并尝试连接到串行端口。

答案 1 :(得分:1)

您可以尝试通过串口将通信移动到单独的线程,或设置较低的超时。

答案 2 :(得分:1)

根据MSDN,

DispatcherTimer是:

  

集成到Dispatcher队列中的计时器   在指定的时间间隔和指定的优先级处理。

这意味着它在Dispatcher pupms消息的同一个线程上运行。因此,在您的计时器请求过程中,它将停止执行或处理队列中的其他内容。

要解决此问题,请使用在System.Timers.Timer类事件中连接到serail端口的代码,该事件在单独的线程上运行,因此在执行期间不会阻塞UI

答案 3 :(得分:1)

您可以使用Thread,也可以使用Task TPL。您还可以在SerialPort类上使用一些事件,例如DataReceived

如何将其从Read更改为BeginRead。然后,您可以使用AsyncCallback

byte[] received = new byte[port.BytesToRead];
result = port.BaseStream.BeginRead(received 
            , 0, port.BytesToRead, new AsyncCallback(ReadCallBack), port.BaseStream);


private void ReadCallBack(IAsyncResult ar)
    {            
        Stream stream = (Stream)ar.AsyncState;

        // Do reading here?
    }