Abhishek Kumar
Abhishek Kumar

Reputation: 352

Need an Alternate Method to Get a 20 millisecond resolution Cycle

I need to read a message coming from a CAN network every 20ms. For this purpose I made a function which works defined below. It's kind of work around, but does the job.

    public void Read_CAN_RC_Message()
    {
        bool a = true;
        while (a)
        {
            Stopwatch t = Stopwatch.StartNew();
            // My actual Function Starts Here
            int rMulti = CANbus.CAN_Receive_multiple_nonblock(recieveMsg, 5);

            if (0 < rMulti)
            {
                count++;

                for (int k = 0; k < rMulti; k++)
                {
                    if (recieveMsg[k].id == 0x400)
                    {
                        currentX = 0;
                        currentY = 0;
                        currentX = currentX | recieveMsg[k].data[3];
                        currentX = (currentX << 8) | recieveMsg[k].data[2];
                        currentX = (currentX << 8) | recieveMsg[k].data[1];
                        currentX = (currentX << 8) | recieveMsg[k].data[0];
                        currentY = currentY | recieveMsg[k].data[7];
                        currentY = (currentY << 8) | recieveMsg[k].data[6];
                        currentY = (currentY << 8) | recieveMsg[k].data[5];
                        currentY = (currentY << 8) | recieveMsg[k].data[4];
                    }
                // Function Ends here
                int timestep = t.Elapsed.Milliseconds; // To measure Time Needded to complete the Operation
                timeCheck.Rows.Add(timestep,str);             

            }
            while (t.Elapsed < timer20ms)
            {
                // Nothing
            }
        }
    }

I soon realized that the operation takes 2ms to complete and for remaining 18ms my processor is stuck in an infinite loop. So this operation requires its own separate thread which always works (using the Processor). Is there a neater a more professional way to do this. Please suggest. I need to run this application in a separate thread as it has to run always as soon as the application starts till it shuts down.

Upvotes: 4

Views: 246

Answers (5)

Zotta
Zotta

Reputation: 2603

I recommend Thread.Sleep with a few additional tricks:

  1. Request a high timer resolution: MSDN: Obtaining and Setting Timer Resolution. You can probably find the C# signatures on pinvoke.net

  2. Use the Stopwatch class to calculate the length of the wait period. Do not call Sleep if the period is less than 1ms.

  3. Increase your thread priority using the Thread class

  4. Do expensive calculations on another thread if possible.

  5. Optional: Use busy waiting after Thread.Sleep for up to 1 ms in order to get better pricision. Use Thread.SpinWait for this.

Combining 1. and 2. gave me enough precision to implement a frame brake for a game without causing stutter/lag.

Upvotes: 0

gabba
gabba

Reputation: 2880

In case of device that send data periodicaly you must use asynchronous way to get data.

To provide you complete solution or advice, show the full contract of CANbus dll.

Also it would be better if you explained the main task.

Upvotes: 0

Abhishek Kumar
Abhishek Kumar

Reputation: 352

I found a solution at other website. I am placing the Link, I have tested this and it works amazingly http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer Hope it will help people in future. Thanks for all your help. It is really appreciated. @idstam Thanks for sending me the MSDN Link. It taught me a thing or two.

Upvotes: 0

Jigneshk
Jigneshk

Reputation: 348

you can use the Timer with 20ms Timer_Elpased. Or you can put your thread in sleep mode for 15-20 milli secs. Thread.Sleep(20)

Upvotes: 1

idstam
idstam

Reputation: 2878

Use the Timer class. You can make it call your function every 20ms.

https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx

Upvotes: 2

Related Questions