C# 写入串行COM端口时,如何实现异步功能?

C# 写入串行COM端口时,如何实现异步功能?,c#,asynchronous,serial-port,mutex,C#,Asynchronous,Serial Port,Mutex,我有一个程序,每X秒通过串行COM报告一个文件夹结构的大小。 当用户通过串行COM发送命令时,它还能够报告文件夹结构中所有文件的列表 例如: 用户每隔10秒就会获得一次大小信息,有时他们想知道文件列表。因此,他们通过COM端口发送一个“1”,然后程序开始报告文件 我遇到的问题是,两个函数不能同时写入COM端口,因此它开始抛出异常 我想做的是让这两个函数等待另一个函数完成。这是我的密码 这是写入COM端口的简单功能: private void ComWrite(string msg) {

我有一个程序,每X秒通过串行COM报告一个文件夹结构的大小。 当用户通过串行COM发送命令时,它还能够报告文件夹结构中所有文件的列表

例如: 用户每隔10秒就会获得一次大小信息,有时他们想知道文件列表。因此,他们通过COM端口发送一个“1”,然后程序开始报告文件

我遇到的问题是,两个函数不能同时写入COM端口,因此它开始抛出异常

我想做的是让这两个函数等待另一个函数完成。这是我的密码

这是写入COM端口的简单功能:

private void ComWrite(string msg)
{
    ComPort.Write(msg);
}
我称之为这两个功能:

这个报告了文件名:

private void GetFileNames()
{
    fileNames = Directory.GetFiles(textBox1.Text, "*.wav", SearchOption.AllDirectories);
    for (int i = 0; i < fileNames.Length; i++)
    {
        ComWrite((fileNames[i] + "\r\n"));
    }
}
我如何实现异步函数,或者其他一些方法来阻止它们相互碰撞

编辑:请求的代码

下面是表单加载时COM端口的设置

    private void Form1_Load(object sender, EventArgs e)
    {
        label5.Text = "Idle";

        ComPort.BaudRate = Convert.ToInt32("9600");
        ComPort.DataBits = Convert.ToInt16("8");
        ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
        ComPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), "None");
        ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), "None");

    }
您可以通过组合框打开您选择的COM端口,然后单击此处:

   private void btnPortState_Click(object sender, EventArgs e)
    {
        try
        {
            if (btnPortState.Text == "COMPort Closed / Click to Open")
            {
                btnPortState.BackColor = Color.Green;
                btnPortState.Text = "COMPort Open / Click To Close";
                ComPort.PortName = Convert.ToString(cboPorts.Text);
                ComPort.Open();
            }
            else if (btnPortState.Text == "COMPort Open / Click To Close")
            {
                btnPortState.Text = "COMPort Closed / Click to Open";
                btnPortState.BackColor = Color.Firebrick;
                ComPort.Close();
            }
        }
        catch (Exception)
        {
            MessageBox.Show("You must select a COMPORT before opening it.");
        }
    }

我认为您想要的是对您的com端口进行的任何交易的互斥

如果问题是两个不同的线程可以同时开始写入comport,那么可以通过使用信号量来解决

在您的情况下,我猜如果在发送文件名时传输目录大小,那将是不好的。因此,您不能简单地在
ComWrite
中进行snychonize

相反,我建议如下:

课堂上:

//semaphore so only 1 Thread at a time can pass through
private static Semaphore semaphore = new Semaphore(1, 1); //(1,1) -> see comments
OnTimedEvent
中:

if (checkBox1.Checked)
{
    try
    {
        semaphore.WaitOne(); //Increases semaphore counter
        ComWrite(labelText + "\r\n");
        semaphore.Release();
        label9.Text = labelText;
    }
    (...)


就像柜台一样工作。如果计数器达到其最大计数,则没有更多线程可以通过
Wait
调用并等待轮到它们。释放信号量基本上告诉计数器减少,等待的线程现在可以进入。

lock(lockObject)
是你的朋友吗给我们看
ComWrite
@raidensan的代码我已经将其添加到帖子中了,这是一个非常脆弱的结构。您不能更改它,使客户端每隔10秒重新请求文件夹大小(例如,在com端口上使用“2”)?这是有道理的,但在使用它时,它只是卡在信号量上。WaitOne();自从我使用它们已经有一段时间了,可能在初始化时主线程已经将信号量增加了1,而没有调用
Wait()
是否尝试用(0,2)初始化信号量?或者在构造信号量之后直接调用
Release()
。非常抱歉,我完全忽略了第一个参数,甚至没有注意到这是开始计数。NET信号量指定计数器可以输入多少线程。因此,如果它们从0开始,就没有线程可以进入的位置了。因此,调用
Release
应该可以做到这一点。或者使用(1,1)Perfect初始化jsut,它完全符合我的要求。谢谢
if (checkBox1.Checked)
{
    try
    {
        semaphore.WaitOne(); //Increases semaphore counter
        ComWrite(labelText + "\r\n");
        semaphore.Release();
        label9.Text = labelText;
    }
    (...)
private void GetFileNames()
{
    semaphore.WaitOne();
    (...) //writing the file names to ComPort
    semaphore.Release();
}