线程时拒绝C#端口



使用Microsoft Visual Expres,Win Form应用程序在我的应用程序中,我通过串行通信将数据从PC发送到微控制器。它的工作原理是:应用程序从PC发送数据-微控制器做他的程序-在微控制器程序的最后向应用程序发送字符-应用程序接收字符并发送另一个数据。

我的问题是,当我等待来自微控制器的字符时,整个应用程序(在PC中)变得不活动(无法按下任何按钮或关闭程序)。

朋友告诉我试试Threads。我试着用线程来做这件事(我对线程很陌生)。当我运行我的应用程序时,它会抛出一个异常:拒绝访问端口"COM6"。看起来串行端口是在一个线程中打开的,然后其他线程关闭端口

有没有办法将端口设置为对所有线程开放?或者有什么更好的想法可以让我的应用程序在等待微控制器响应时处于活动状态?

有一些带有线程的代码行:

.
.
.
     poslat(data_all);   //sending data function               
     Thread t = new Thread(cakaj);
     t.Start(); // start of thread cakaj
.
.
.

有发送数据的功能

static void poslat(string data)
{
    SerialPort COMport = new SerialPort();
    COMport.PortName = "COM6"; 
    COMport.BaudRate = 1200;
    COMport.DataBits = 8;
    COMport.Parity = Parity.None;
    COMport.StopBits = StopBits.One;
    COMport.Open();
    COMport.Write(data);
    COMport.WriteTimeout = 500;
    COMport.Close();
}

等待来自微控制器的字符的功能

void cakaj()
{
    SerialPort COMport = new SerialPort();
    int byteRead;
    COMport.PortName = "COM6"; // 
    COMport.BaudRate = 1200;
    COMport.DataBits = 8;
    COMport.Parity = Parity.None;
    COMport.StopBits = StopBits.One;
    COMport.Open(); //**Program points there with error message:Acces to the port "COM6" is denied.** 
    do
    { 
        byteRead = COMport.ReadByte();
    } while (byteRead != 75);   // ASCII K = 75
    t.Abort();
   COMport.Close();
    return;
}

您正在使用同一端口COM6创建两个不同的SerialPort COMport实例。您可以做的是将COMport变量作为类的字段,并在poslatcakaj中访问该字段。

此外,您也可以使用DataReceived事件,而不是创建另一个线程。

你的代码看起来像这样。

class YourClass
{
    static SerialPort _COMport;
    int byteRead; //make byteRead a field so you can also share it outside cakaj
    SerialPort COMport //share COMport for poslat and cakaj
    {
        get
        {
            if(_COMport == null)
            {
               CreateCOMport();
            }
            return _COMport;
        }
    }
    void CreateCOMport()
    {
        _COMport = new SerialPort();
        _COMport.PortName = "COM6";
        _COMport.BaudRate = 1200;
        _COMport.DataBits = 8;
        _COMport.Parity = Parity.None;
        _COMport.StopBits = StopBits.One;
        _COMport.DataReceived += cakaj;
        //COMport will listen for any incoming data
        //when there is data available, method cakaj will run
    }
    void poslat(string data)
    {
        if (!COMport.IsOpen)
        {
            COMport.Open();
        }
        COMport.Write(data);
        COMport.WriteTimeout = 500;
    }
    void cakaj(object sender, SerialDataReceivedEventArgs e)
    {
        do
        {
            byteRead = COMport.ReadByte();
        } while (byteRead != 75);
        COMport.Close();
    }
}

编辑:记得在这个类的某个地方调用COMport.Close()。我改变了方法,有很多方法可以改进,但我认为它会起作用。。。

如果希望Forms应用程序的主线程在循环中等待,则必须确保给它处理事件的机会。

你可以这样修改你的等待循环:

do
{ 
    Application.DoEvents(); // handle Windows Forms events
    byteRead = COMport.ReadByte();
} while (byteRead != 75);   // ASCII K = 75

这将确保您的应用程序在等待期间仍然可以响应事件。

当然,只有当应用程序的主线程正在等待时,这才是必要的。后台线程不必这样做,事实上它们也不能这样做。

相关内容

最新更新