最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Wait Mask Requests loop RJCP.IO.Ports after opening a Serial Port in WPF application - Stack Overflow

programmeradmin3浏览0评论

this is my first time asking a question here, and I’m an amateur coder. I’m learning through trial and error, so I apologize in advance if my code causes your eyes to bleed out. I’m currently building an application in WPF using MVVM (.NET 6.0) to manage a shop. I won’t go into too much detail (yes it's a big project for a newbie, yes it's complex and can go wrong in many ways, but the app is working so I, more or less, know what I’m doing). However, I’m stuck on a “problem” that I just can’t wrap my head around.

I have a service that connects my app to a cash register via a serial port, which requires certain "commands". This service uses RJCP.IO.Ports and it's used by one of my ViewModels, and I’ve managed to make it work so that the device responds properly to the XON-XOFF Protocol commands sent to it. However, when I use Device Monitor Studio to monitor the data being sent to the port, I notice that there are hundreds of requests related to a “WaitMask” every second after I open the port. No matter what, I can’t seem to stop them.

The "Request View" shows that these requests are looping endlessly:

000041: I/O Request (DOWN): 2024-11-17 00:14:06,712104 +0,003315
 IOCTL_SERIAL_SET_WAIT_MASK: Set wait mask
    · Wait Mask     = SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING (0x1ff)

000042: I/O Request (UP): 2024-11-17 00:14:06,712203 +0,000099
 IOCTL: IOCTL_SERIAL_SET_WAIT_MASK

000043: I/O Request (DOWN): 2024-11-17 00:14:06,712227 +0,000024
 IOCTL_SERIAL_SET_WAIT_MASK: Set wait mask
    · Wait Mask     = SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING (0x1ff)

000044: I/O Request (UP): 2024-11-17 00:14:06,712318 +0,000091
 IOCTL: IOCTL_SERIAL_SET_WAIT_MASK

000045: I/O Request (DOWN): 2024-11-17 00:14:06,713507 +0,001189
 IOCTL: IOCTL_SERIAL_GET_COMMSTATUS

000046: I/O Request (UP): 2024-11-17 00:14:06,713547 +0,000040
 IOCTL_SERIAL_GET_COMMSTATUS: Retrieve COM status
    · Errors                    = 0x0
    · Hold reasons              = 0x0
    · In queue                  = 0
    · Out queue                 = 0
    · EOF received              = false
    · Wait for immediate        = false

000047: I/O Request (DOWN): 2024-11-17 00:14:06,714582 +0,001035
 IOCTL_SERIAL_WAIT_ON_MASK: Start waiting for event

000048: I/O Request (DOWN): 2024-11-17 00:14:06,717894 +0,003312
 IOCTL_SERIAL_SET_WAIT_MASK: Set wait mask
    · Wait Mask     = SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING (0x1ff)

000049: I/O Request (UP): 2024-11-17 00:14:06,718000 +0,000106
 IOCTL_SERIAL_WAIT_ON_MASK: Wait for event
    · Wait Mask     = 0x0

000050: I/O Request (UP): 2024-11-17 00:14:06,718037 +0,000037
 IOCTL: IOCTL_SERIAL_SET_WAIT_MASK

000051: I/O Request (DOWN): 2024-11-17 00:14:06,718046 +0,000010
 IOCTL: IOCTL_SERIAL_GET_COMMSTATUS

000052: I/O Request (UP): 2024-11-17 00:14:06,718093 +0,000046
 IOCTL_SERIAL_GET_COMMSTATUS: Retrieve COM status
    · Errors                    = 0x0
    · Hold reasons              = 0x0
    · In queue                  = 0
    · Out queue                 = 0
    · EOF received              = false
    · Wait for immediate        = false

000053: I/O Request (DOWN): 2024-11-17 00:14:06,720573 +0,002480
 IOCTL_SERIAL_SET_WAIT_MASK: Set wait mask
    · Wait Mask     = SERIAL_EV_RXCHAR | SERIAL_EV_RXFLAG | SERIAL_EV_TXEMPTY | SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK | SERIAL_EV_ERR | SERIAL_EV_RING (0x1ff)

000054: I/O Request (UP): 2024-11-17 00:14:06,720611 +0,000038
 IOCTL: IOCTL_SERIAL_SET_WAIT_MASK

000055: I/O Request (DOWN): 2024-11-17 00:14:06,720643 +0,000032
 IOCTL: IOCTL_SERIAL_GET_COMMSTATUS

000056: I/O Request (UP): 2024-11-17 00:14:06,720690 +0,000046
 IOCTL_SERIAL_GET_COMMSTATUS: Retrieve COM status
    · Errors                    = 0x0
    · Hold reasons              = 0x0
    · In queue                  = 0
    · Out queue                 = 0
    · EOF received              = false
    · Wait for immediate        = false

000057: I/O Request (DOWN): 2024-11-17 00:14:06,720710 +0,000021
 IOCTL_SERIAL_WAIT_ON_MASK: Start waiting for event

I’m not sure what I should do. I’m not familiar with how serial ports work; I’ve just tried my best to figure it out. Below is the code for my service:

using App.Contracts.Services;
using App.ViewModels;
using RJCP.IO.Ports;
using System.IO;
using System.Text;
namespace App.Services;
public class CashRegisterService : ICashRegisterService
{
    private readonly Logger logSent;
    private readonly Logger logExc;
    private SerialPortStream P;
    public SerialPortStream Port => P;
    private readonly object portLock = new();
    private bool isPortOpen;

    public CashRegisterService()
    {
        string defaultPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");

        if (!Directory.Exists(defaultPath))
            Directory.CreateDirectory(defaultPath);

        logSent = new Logger(defaultPath, ".log", "Rs232");
        logExc = new Logger(defaultPath, ".exc", "Rs232Exc");
    }

    public void SetPort(int portNum = 4, int baudRate = 9600, int databits = 8,
        Parity parity = Parity.None, StopBits stopBits = StopBits.One)
    {
        if (portNum <= 0)
            throw new ArgumentException("Port number should be > 0.");

        P = new SerialPortStream
        {
            PortName = $"COM{portNum}",
            BaudRate = baudRate,
            DataBits = databits,
            Parity = parity,
            StopBits = stopBits,
            Handshake = Handshake.None
        };
        P.DiscardNull = false;
        P.DiscardInBuffer();
        P.DiscardOutBuffer();
    }
    public void OpenConnection()
    {
        lock (portLock)
        {
            if (P == null)
                throw new InvalidOperationException("Port not found.");

            if (!isPortOpen)
            {
                try
                {
                    P.Open();
                    P.WriteTimeout = 500;
                    P.ReadTimeout = 500;
                    P.DiscardInBuffer();
                    P.DiscardOutBuffer();
                    isPortOpen = true;
                    WriteLog($"Connection opened {P.PortName} param: \"{P.BaudRate}, {P.DataBits}, {P.Parity}, {P.StopBits}, {P.Handshake}\"");
                }
                catch (Exception ex)
                {
                    WriteLog($"Error: {ex.Message}", true);
                    throw;
                }
            }
        }
    }

    public string ReadAnswer()
    {
        StringBuilder answer = new StringBuilder();
        try
        {
            int bytesRead;
            byte[] buffer = new byte[256];

            do
            {
                bytesRead = P.Read(buffer, 0, buffer.Length);
                answer.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
            }
            while (P.BytesToRead > 0);
        }
        catch (TimeoutException)
        {
            WriteLog("Timeout: No answer.");
        }
        return answer.ToString();
    }

    public void CloseConnection()
    {
        lock (portLock)
        {
            if (isPortOpen)
            {
                try
                {
                    P.Close();
                    isPortOpen = false;
                    WriteLog($"Connection {P.PortName} closed.");
                }
                catch (Exception ex)
                {
                    WriteLog($"Error: {ex.Message}", true);
                }
            }
        }
    }

    public void SendCommand(string command)
    {
        lock (portLock)
        {
            if (!isPortOpen)
                throw new InvalidOperationException("Serial Port is closed.");

            try
            {              
                P.Write(command);
                WriteLog($"command sent: {command}");

                Thread.Sleep(100);

                try
                {
                    string response = ReadAnswer();
                    if (!string.IsNullOrWhiteSpace(response))
                        WriteLog($"Datas received: {response}");
                    else
                        WriteLog("Any data received.");
                }
                catch (TimeoutException)
                {
                    WriteLog("Timeout: No answer.");
                }
            }
            catch (Exception ex)
            {
                WriteLog($"Error for command '{command}': {ex.Message}", true);
                throw;
            }
        }
    }

    private void WriteLog(string message, bool isError = false)
    {
        try
        {
            if (isError)
                logExc.writeLog(message);
            else
                logSent.writeLog(message);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error Log: {ex.Message}");
        }
    }
    //rest of the code
}

Again I am sorry if this code looks a mess to you (also English is not my first language, so I apologize if anything seems weird or grammatically incorrect)

I tried many things but there are no clear methods in the RJCP.IO.Ports library to set the WaitMask events. Am I missing something?

发布评论

评论列表(0)

  1. 暂无评论