C # - periodically reading data and Thread.Sleep ()

my C # application reads data from a special USB device. Data is read as so-called โ€œmessagesโ€, each of which has 24 bytes. The number of messages to be read per second may vary (the maximum frequency is quite high, about 700 messages per second), but the application must read them.

The only way to read messages is to call the ReadMessage function, which returns a single message read from the device. The function is from an external DLL, and I cannot change it.

My solution: I have a separate thread that runs all the time during the start of the program, and the only task is to read messages in a loop. Received messages are then processed in the main thread of the application.

The function executed in the "read stream" is as follows:

private void ReadingThreadFunction() {
    int cycleCount;
    try {
        while (this.keepReceivingMessages) {
            cycleCount++;
            TRxMsg receivedMessage;
            ReadMessage(devHandle, out receivedMessage);

            //...do something with the message...
        }
    }
    catch {
        //... catch exception if reading failed...
    }
}

This solution works fine, and all messages are received correctly. However, the application consumes too many resources, the processor of my computer is running at more than 80%. Therefore, I would like to reduce it.

Thanks to the "cycleCount" variable, I know that the "speed" of the flow is about 40,000 cycles per second. This is too much, since I need to receive a maximum of 700 messages / sec. (and the device has a buffer for about 100 messages, so the cycle speed may even be slightly lower)

, 1 Thread.Sleep(1); . , , 70 , . , , , , 1 .

, : ( ), Thread.Sleep? - Thread, Threading.Timer ThreadPool?

. , , , , , .

+3
9

:

//...do something with the message... 

// If the message is null, it indicates that we've read everything there is to be read.
// So lets sleep for 1ms to give the buffer chance to receive a few extra messages.
If (theMessage == null) // Buffer is empty as we failed to read a new message
{
    Thread.Sleep(1);
}

, , , , .

-2

. . . , ( , ). 10 , , 100 . .

+2

VS2010. , , , .

0

ReadMessage, ?

, , . 1 .

0

Thread.Sleep . , . "" 1 . . .

, DLL . , DLL . , DLL .

, , .

EDIT:

, , DispatcherTimer . DispatcherTimer , . ( , , ), . , , .

:

// Creating the DispatcherTimer
var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = TimeSpan.FromMilliseconds(1);
dispatcherTimer.Start();


private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    if (this.ProcessingEvents)
        return;

    this.ProcessingEvents = true;

    var messagesLeft = true;

    while (messagesLeft)
    {
        TRxMsg receivedMessage;
        ReadMessage(devHandle, out receivedMessage);

        // Process message
        // Set messagesLeft to false if no messages left
    }

    this.ProcessingEvents = false;
}
0

AutoResetEvent - 1 ?

private void ReadingThreadFunction() {

    try {
            var autoReset = new AutoResetEvent(false);
            autoReset.WaitOne(1);
            TRxMsg receivedMessage;
            ReadMessage(devHandle, out receivedMessage);

            //...do something with the message...
        }
    }
    catch {
        //... catch exception if reading failed...
    }
}

EDIT: , , ...

0

, . , , 700 , , 700 . . .

// Queue Start
ProcessQueue.Instance.Start();

// Queue Stop
ProcessQueue.Instance.Stop();

:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Diagnostics;

namespace Service.Queue
{
    /// <summary>
    /// Process Queue Singleton Class
    /// </summary>
    class ProcessQueue : IDisposable
    {

        private static readonly ProcessQueue _instance = new ProcessQueue();
        private bool _IsProcessing = false;
        int _maxMessages = 700;

        public bool IsProcessing
        {
            get { return _IsProcessing; }
            set { _IsProcessing = value; }
        }

        ~ProcessQueue()
        {
            Dispose(false);
        }

        public static ProcessQueue Instance
        {
            get
            {
                return _instance;
            }
        }


        /// <summary>
        /// Timer for Process Queue
        /// </summary>
        Timer timer = new Timer();

        /// <summary>
        /// Starts Process Queue
        /// </summary>
        public void Start()
        {
            timer.Elapsed += new ElapsedEventHandler(OnProcessEvent);
            timer.Interval = 1000;
            timer.Enabled = true;
        }

        /// <summary>
        /// Stops Process Queue
        /// </summary>
        public void Stop() {
            _IsProcessing = false;
            timer.Enabled = false;
        }

        /// <summary>
        /// Process Event Handler
        /// /// </summary>
        private void OnProcessEvent(object source, ElapsedEventArgs e)
        {
            if (!_IsProcessing)
            {
                _IsProcessing = true;

        for (int i = 0; i < _maxMessages; i++)
                {
            TRxMsg receivedMessage;
            ReadMessage(devHandle, out receivedMessage);
        }

                _IsProcessing = false;
            }

        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                timer.Dispose();
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

    }
}
0
  • , API, DLL. ? , , , , .

  • , . , . , , , .

0

Thread.SpinWait:

SpinWait , . , .

Contrast this with the Sleep method. The thread that causes Sleep gives the rest of the current current processor time, even if the indicated interval is zero. Specifying a nonzero interval for Sleep removes the thread from consideration by the thread scheduler before the time interval expires.

SpinWait is a project waiting, not inferior to the current time interval

It is designed for situations where you know that you want to do something in a very short time, so the loss of your time will be excessive.

-1
source

Source: https://habr.com/ru/post/1747524/


All Articles