1

我目前正在开发需要读取串行端口的 C# 应用程序。在 UI 中,有一个 ON/OFF 按钮,用户可以点击它来开始和停止从串口读取数据。如果我连续单击按钮打开和关闭。它引发了异常 - 访问 COM3 被拒绝,甚至说“设备未连接”。谁能建议一种更好的方法来实现能够解决上述情况的串口功能?这是我使用的代码:

**// Start reading data from serial port**
public override void StartReading(string portname)
{
    try
    {
        int k = int.Parse(portname.Replace("COM", ""));
        if (startThread != null)
        {
            startThread.Abort();
            startThread = null;
        }

        startThread = new Thread(new ThreadStart(delegate
        {
            isActive = true;
            try
            {
                using (SerialPort sp = new SerialPort(portname))
                {
                    if (!isActive)
                    {
                        DisposeBT(sp);
                        return;
                    }
                    sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
                    if (!isActive)
                    {
                        DisposeBT(sp);
                        return;
                    }

                    if (!isActive)
                    {
                        DisposeBT(sp);
                        return;
                    }
                    else
                    {
                        Thread.Sleep(6500);
                        try
                        {
                            if (sp != null && !sp.IsOpen)
                            {
                                sp.Open();
                            }

                        }
                        catch (Exception ex)
                        {
                           Logger.Warn("Failed to open the serial port for HRM once. Try it again.");
                            Logger.Error(ex);
                            ////////////////////// new added below
                            if(sp !=null && sp.IsOpen)
                            {
                                sp.Dispose();
                            }
                            Thread.Sleep(6500);
                            if (IsPortAvailable(k))
                            {
                                try
                                {
                                    if (sp != null && !sp.IsOpen)
                                    {
                                        sp.Open();
                                    }

                                }
                                catch (Exception ex1)
                                {
                                    ////////////////////// new added below
                                    if (sp != null && sp.IsOpen)
                                    {
                                        sp.Dispose();
                                    }
                                    Logger.Warn("Failed to open the serial for HRM twice.");
                                    Logger.Error(ex1);
                                    // return;
                                }
                            }
                        }

                    }
                    while (true)
                    {

                        if (!isActive)
                        {
                            DisposeBT(sp);
                            break;
                        }
                    }
                    if (!isActive)
                    {
                        DisposeBT(sp);
                        return;
                    }
                    DisposeBT(sp);
                }
            }
            catch (Exception ex)
            {
                Logger.Warn("Exception thrown for HRM.");
                Logger.Error(ex);
            }

        }));
        startThread.IsBackground = true;
        startThread.Priority = ThreadPriority.Highest;
        startThread.Start();
    }
    catch (Exception ex)
    {
        Logger.Warn("Failed to start reading for HRM02I3A1 bluetooth device.");
        Logger.Error(ex);
    }
}

// Stop reading data from serial port
public override void StopReading()
{
    try
    {
        isActive = false;
    }
    catch { }
}

// event handler for the serial port to read data from sp.
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (isActive)// && startThread.IsAlive
    {
        SerialPort sp1 = (SerialPort)sender;
        try
        {
            sp1.Read(data, 0, 8);
            decoder.Decode(data);
        }
        catch(Exception ex)
        {
            Logger.Warn("------data received from Serial Port error for HRM-------");
            Logger.Error(ex);
        };
    }   
}
4

2 回答 2

2

首先制作接受取消事件的后台工作线程。

在该DoWork方法中,您可以编写类似的内容

void DoWork{
    // init com port
    while(no body cancelled the background worker){
         // if there any waiting data receive and process it. do not use event handlers
    }
    // close the serial port so you can open it again later.
}

此外,如果您想取消后台工作,那将是小菜一碟

// send cancel command.
// wait till it is canceled.
于 2013-03-13T18:11:00.993 回答
0

尝试startThread.Join()在调用后直接添加startThread.Abort().

查看有关 Thread.Abort 的 msdn 文档,也许您还应该检查join 的作用

于 2013-03-13T18:26:05.163 回答