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

标签 c# asynchronous serial-port mutex

我有一个程序,每 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"));
    }
}

这是一个计时器并报告文件夹大小:

public void OnTimedEvent(object source, ElapsedEventArgs elapsed)
{
    folderSize = DirSize(new DirectoryInfo(textBox1.Text)) / 1000000;

    string labelText = folderSize.ToString() + "Mb";

    label3.Text = labelText;

    if (checkBox1.Checked)
    {
        try
        {
            ComWrite(labelText + "\r\n");
            label9.Text = labelText;
        }
        catch (Exception)
        {
            MessageBox.Show("Please Open COMPORT before sending command");
        }
    }
}

我怎样才能实现异步函数,或者其他一些方法来阻止它们相互重叠?

编辑:请求的代码。

此处是在表单加载时设置 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 端口进行的任何交易的互斥。

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

在您的情况下,我猜测如果在您发送文件名时传输目录大小并不是一件好事。所以你不能简单地在 ComWrite 中同步。

相反,我会提出以下建议:

在类里面:

//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;
    }
    (...)

private void GetFileNames()
{
    semaphore.WaitOne();
    (...) //writing the file names to ComPort
    semaphore.Release();
}

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

关于c# - 写入串行 COM 端口时如何实现异步功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50528188/

相关文章:

c# - 获取 Windows Phone 7.1 设备 ID

mysql - 节点MYSQL请求,异步问题

C语言,串口阅读器

python - Python中的半双工串行通信

c# - public static vs static public - 有区别吗?

c# - 如果 StringBuilder 是可变的,那么为什么 StringBuilder 方法返回一个 StringBuilder 对象?

Javascript嵌套For循环在返回数组时不更新数组

javascript - Node 数组异步错误

java - 处理时重新连接串口

c# - 如何检查 ViewBag 属性是否为空或不存在