Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 接收到的c#Serialport数据事件处理程序_Multithreading_Serial Port_Backgroundworker_Binaryreader_Binarywriter - Fatal编程技术网

Multithreading 接收到的c#Serialport数据事件处理程序

Multithreading 接收到的c#Serialport数据事件处理程序,multithreading,serial-port,backgroundworker,binaryreader,binarywriter,Multithreading,Serial Port,Backgroundworker,Binaryreader,Binarywriter,我目前正在使用WPF从serialport读取数据。我能够从serialport读取数据并使用Binarywriter将其写入文件 我现在面临的问题是: 我想分析这些数据。我已经开发了一个包含用例结构的函数来分割我在SerialPortDataHandler中读取的数据。目的是分析捕获的数据。但我的程序只是在从串口接收数据。分析这些数据并不容易 这是我从一些帖子中读到的几个选项,可能是解决我问题的方法: Backgroundworker:如果是,那么我如何才能获取我当前的程序 线程:我试过了,

我目前正在使用WPF从serialport读取数据。我能够从serialport读取数据并使用Binarywriter将其写入文件

我现在面临的问题是: 我想分析这些数据。我已经开发了一个包含用例结构的函数来分割我在SerialPortDataHandler中读取的数据。目的是分析捕获的数据。但我的程序只是在从串口接收数据。分析这些数据并不容易

这是我从一些帖子中读到的几个选项,可能是解决我问题的方法:

  • Backgroundworker:如果是,那么我如何才能获取我当前的程序

  • 线程:我试过了,但不起作用。我的程序正在写文件中的字节&而不是启动我声明的线程

有人能给我推荐一个更好的选择吗

我的代码:

private void port_DataReceived(Object sender, SerialDataReceivedEventArgs e) {
  BinaryWriter writer=new BinaryWriter(File.Open("c:\\temp\\lbus2snifflog1.txt", FileMode.Append));
  int bytes=comport.Read(buffer, 0, 4096);
  for (int i=0;
  i < bytes;
  i++) {
    //writer.Write(buffer, 0, bytes);             // Write the data to the file on temp folder
    data.Enqueue(buffer[i]); // Enqueue data from the buffer
    writer.Write(buffer, 0, bytes);
  }
  //writer.Write(buffer, 0, bytes);
  writer.Flush(); // Send all remaining data to the writer
  writer.Close(); // Close the writer
  /*Initilaise the Thread for the Analysis*/
  Thread Analyser=new Thread(datacollection);
  Analyser.Start();
}
private void port\u DataReceived(对象发送方,SerialDataReceivedEventArgs e){
BinaryWriter=新的BinaryWriter(File.Open(“c:\\temp\\lbus2snifflog1.txt”,FileMode.Append));
int bytes=comport.Read(缓冲区,04096);
对于(int i=0;
i<字节;
(i++){
//Write.Write(缓冲区,0,字节);//将数据写入临时文件夹上的文件
data.Enqueue(buffer[i]);//将数据从缓冲区排队
writer.Write(缓冲区,0,字节);
}
//writer.Write(缓冲区,0,字节);
writer.Flush();//将所有剩余数据发送给writer
writer.Close();//关闭writer
/*初始化线程以进行分析*/
线程分析器=新线程(数据采集);
分析器。启动();
}

我认为您应该运行设置为IsBackground=true的线程; 我就是这样用的

new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            //Do what you want to Run in background here
        }).Start();
或者简单的设置就可以了:

analyzer.IsBackground=true;
分析器。启动()

编辑 对于您的情况,不知道这是否是最好的方法,但这可能有效

在主线程中有一个ConcurrentDictionary。在BackgroundWorker线程中,您从ConcurrentDictionary获取数据。然后向主线程报告处理后的数据

下面是一个工作场景

例如:

class MyClass
{
    private ConcurrentDictionary<int, string> serialPortsQueue =
        new ConcurrentDictionary<int, string>();

    private BackgroundWorker _worker;
    public MyClass()
    {
        _worker = new BackgroundWorker()
        {
            WorkerSupportsCancellation = true,
            WorkerReportsProgress = true
        };

        _worker.DoWork += DeviceDataAcquisition_DoWork;
        _worker.ProgressChanged += DeviceDataAcquisition_ProgressChanged;
        _worker.RunWorkerCompleted += DeviceDataAcquisition_RunWorkerCompleted;
        _worker.RunWorkerAsync();

        System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: begin add first data");
        serialPortsQueue.TryAdd(1, "data 1");
        serialPortsQueue.TryAdd(2, "data 2");
        serialPortsQueue.TryAdd(3, "data 3");
        serialPortsQueue.TryAdd(4, "data 4");
        serialPortsQueue.TryAdd(5, "data 5");
        serialPortsQueue.TryAdd(6, "data 6");
        serialPortsQueue.TryAdd(7, "data 7");
        System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: end add first data");
        Thread.Sleep(2000);
        System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: begin add second data");
        serialPortsQueue.TryAdd(8, "data 8");
        System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: end add second data");
    }

    private void DeviceDataAcquisition_DoWork(object sender, DoWorkEventArgs e)
    {
        // backgroundworker thread
        if (sender is BackgroundWorker worker)
        {
            //just demo propose
            int cnt = 0;

            while (true)
            {
                if (worker.CancellationPending)
                    break;

                if (serialPortsQueue.Count > 0)
                {
                    KeyValuePair<int, string> kv = serialPortsQueue.ElementAt(0);
                    serialPortsQueue.TryRemove(kv.Key, out string value);

                    //just demo propose
                    // Simulate some processing
                    Thread.Sleep(1000);

                    worker.ReportProgress(0, kv);

                    //just demo propose
                    cnt++;
                }

                //just demo propose
                if (cnt == 8)
                    break;
            }
        }
    }

    private void DeviceDataAcquisition_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // main thread
        if (e.UserState is KeyValuePair<int, string> kv)
        {
            System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: {kv.Key} -> {kv.Value}");
        }
    }

    private void DeviceDataAcquisition_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (sender is BackgroundWorker worker)
        {
            worker.DoWork -= DeviceDataAcquisition_DoWork;
            worker.ProgressChanged -= DeviceDataAcquisition_ProgressChanged;
            worker.RunWorkerCompleted -= DeviceDataAcquisition_RunWorkerCompleted;
            worker.Dispose(); // i think this does nothing...
            System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: end backgroundworker");
        }
    }
}
class-MyClass
{
私有ConcurrentDictionary serialPortsQueue=
新的ConcurrentDictionary();
私人背景工人;
公共MyClass()
{
_worker=新的BackgroundWorker()
{
WorkerSupportsScanCellation=true,
WorkerReportsProgress=true
};
_worker.DoWork+=设备数据采集\u DoWork;
_worker.ProgressChanged+=设备数据采集\u ProgressChanged;
_worker.RunWorkerCompleted+=设备数据采集\u RunWorkerCompleted;
_worker.RunWorkerAsync();
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:开始添加第一个数据”);
serialportsquee.TryAdd(1,“数据1”);
serialportsquee.TryAdd(2,“数据2”);
serialportsquee.TryAdd(3,“数据3”);
serialportsquee.TryAdd(4,“数据4”);
serialportsquee.TryAdd(5,“数据5”);
serialportsquee.TryAdd(6,“数据6”);
serialportsquee.TryAdd(7,“数据7”);
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:end add first data”);
《睡眠》(2000年);
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:开始添加第二个数据”);
serialportsquee.TryAdd(8,“数据8”);
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:end add second data”);
}
私有无效设备数据采集(对象发送方,DoWorkEventArgs e)
{
//底层加工螺纹
if(发送方为后台工作人员)
{
//只是提议
int-cnt=0;
while(true)
{
if(工作人员取消挂起)
打破
如果(serialPortsQueue.Count>0)
{
KeyValuePair kv=serialPortsQueue.ElementAt(0);
serialPortsQueue.TryRemove(千伏键,输出字符串值);
//只是提议
//模拟一些过程
睡眠(1000);
工人报告进度(0千伏);
//只是提议
cnt++;
}
//只是提议
如果(cnt==8)
打破
}
}
}
私有无效设备数据采集\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
//主线
如果(例如,用户状态为KeyValuePair kv)
{
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:{kv.Key}->{kv.Value}”);
}
}
私有无效设备数据采集\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
if(发送方为后台工作人员)
{
worker.DoWork-=设备数据采集\u DoWork;
worker.ProgressChanged-=设备数据采集_ProgressChanged;
worker.RunWorkerCompleted-=设备数据采集\u RunWorkerCompleted;
worker.Dispose();//我认为这没有任何作用。。。
System.Diagnostics.Debug.WriteLine($“{DateTime.Now}:end backgroundworker”);
}
}
}
您可以在窗口输出->调试结果中看到


希望这有帮助。

结果没有变化。它还在交,谢谢你的详细描述。希望我在工作中有一个疑问,那就是为什么你要用Thread.Sleep(100)??它不会因为serialport连续接收数据而丢失数据吗?对于我来说,100ms是可以的。对你来说,这不是我的梦想。取决于用例。我用它来读取modbus数据,我确信数据不会在100毫秒内改变。好的。那么在我的情况下,我不能承受数据丢失,因为它的速度是6Mbps。后台工作程序不需要任何datareceived处理程序?好的,那么只需删除System.Threading.Thread.Sleep(100)。到“datareceived处理程序”