0

I am currently reading data from serialport using WPF. I am able to read data from serialport & write it in File using Binarywriter.

What Problem I am facing right now is: I want to Analyse this data. I have developed one function which contains Use case structures to split the data which i read in serialport datahandler. Purpose is to Analyse captured data. But my program is just hanging on in receiving data from Serialport. Its not approaching down to Analyse the data.

This are few Options which i read from some Posts which may be a solution for my problem:

  • Backgroundworker: If yes then how i can fetch in my current program?

  • Threading: I tried it but its not working. My program is handing on writing the Bytes in the file & not going down to start the thread which i declared.

So can anybody suggest me a better option?

My code:

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();
}
Sumit
  • 1
  • 5
  • The question is missing your actual problem. You just jump into options without clearly telling what the problem is. You say you're able to read & write data, and then we should tell you how to fix a non-existing problem – James Z Jul 07 '17 at 20:26
  • Sorry. I have added some more Details.. – Sumit Jul 10 '17 at 06:11

2 Answers2

0

I think you should run thread with setting IsBackground = true; I use it like that

new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            //Do what you want to Run in background here
        }).Start();

or maybe simple setting will do the job :

Analyser.IsBackground = true; Analyser.Start();

0

Edit For your case, don't know if this is best approach, but this may work.

You have a ConcurrentDictionary in main thread. In BackgroundWorker thread you get the data from the ConcurrentDictionary. Then you report to main thread the processed data.

Here is a working scenario.

Example:

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");
        }
    }
}

You can see in the window Output -> Debug the results.

Hope this helps.

bruno.almeida
  • 2,746
  • 1
  • 24
  • 32
  • Thank you for Detail description. Hopwever i have one doubt- In _DoWork why you are using Thread.Sleep(100)?? Will it not lose data because serialport is contineously receiving data? – Sumit Jul 07 '17 at 11:33
  • For me 100ms is ok. for you it my not be. Depends on the use case. I am using it to read modbus data and i am sure data wont change in less than 100ms. – bruno.almeida Jul 07 '17 at 11:37
  • Ok. Then in my case i cant afford to lose data as its 6 Mbps. We dont Need any datareceived handler for Background worker? – Sumit Jul 07 '17 at 11:49
  • Ok, then just remove the System.Threading.Thread.Sleep(100). To the "datareceived handler" i am using the DeviceDataAcquisition_ProgressChanged. – bruno.almeida Jul 07 '17 at 11:59
  • I may have misunderstood your question. Do you want to read the data in another thread or process the data in another thread? – bruno.almeida Jul 07 '17 at 12:00
  • I want to read data in datareceivedhandler & process data in another thread. Like i have Queue which act as ring buffer to enqueue all serialport data & i want to simultaneously process it (Dequeue). – Sumit Jul 07 '17 at 12:02
  • O, I misunderstood your question. In the port_DataReceived method do you want to wait for the result or is it just fire and forget? – bruno.almeida Jul 07 '17 at 12:06
  • It should just initialise Event of Data Processing in parallel. Intension is contineously write data in datalogger & process it so that Queue will not be overflooded. Like One thread to write data & one to process. How i can do same in Backgroundwork? – Sumit Jul 07 '17 at 12:10
  • See my edits. Don't know if BackgroundWorker is the best approach, but it is still possible. – bruno.almeida Jul 07 '17 at 13:52