Home > Back-end >  Delay in while loop and its precision
Delay in while loop and its precision

Time:03-30

I am writing C# code to make data acquire system from FPGA with USB communication and not that familiar with C#. The system received data continuously at regular intervals through USB. Data is continuously received only when DOPPLER_NUM = 1, and while (DOPPLER_NUM == 1) is that process. And there are two problems in operation.

  1. When I operate code without Delay(1) in while loop, the program is completely stopped and none of the buttons in the program works.

  2. I used Delay function to solve the problem, and it works. But, the delay I want is 1ms and it actually varies from 1-15ms when I measured it with Stopwatch function.

        public void Delay(int MS)
        {
            DateTime ThisMoment = DateTime.Now;
            TimeSpan Duration = new TimeSpan(0, 0, 0, 0, MS);
            DateTime AfterWards = DateTime.Now.Add(Duration);

            while (AfterWards >= ThisMoment)
            {
                System.Windows.Forms.Application.DoEvents();
                ThisMoment = DateTime.Now;
            }
            return;
        }
int DOPPLER_NUM = 0;

private void Doppler_Start_Click(object sender, EventArgs e)
        {
            
                int transmit_mode = 1; 

                if (DOPPLER_NUM == 0)
                {
                    DOPPLER_NUM = 1;
                    transmit_mode = 1;
                }
                else
                {
                    DOPPLER_NUM = 0;
                    transmit_mode = 0;
                    cnt4GS = 0;
                }

                CyBulkEndPoint Inednpt1;

                Inednpt1 = MyDevice.EndPointOf(0x86) as CyBulkEndPoint;

                int bytes1 = Convert.ToInt32(256);
                int bytes2 = bytes1 * 2;

                bool bXferCompleted = false;

                bool IsPkt = false;

                byte[] buffer4GS = new byte[400 * 256];

                byte[] buffer1 = new byte[bytes2];
                byte[] Data_buf = new byte[bytes1];

                while (DOPPLER_NUM == 1)
                {
                    Stopwatch clk1 = new Stopwatch();
                    clk1.Start();

                    Delay(1);
  
                    clk1.Stop();
                    opertime.Text = (clk1.ElapsedTicks * 100 / 1000).ToString()   " us";                    

                    if (MyDevice != null)
                    {
                        if (Inednpt1 != null)
                        {                           
                            bXferCompleted = Inednpt1.XferData(ref buffer1, ref bytes2, IsPkt); // Data receiving from USB
                                
                                
                            Data_buf = Doppler_Processing(buffer1, bytes2);

                                
                                if (cnt4GS >= 0 && cnt4GS <= 399)
                                {
                                    Buffer.BlockCopy(Data_buf, 0, buffer4GS, cnt4GS * 256, 256);

                                    cnt4GS  ;
                                }
                                else if (cnt4GS >= 400)
                                {
                                    Buffer.BlockCopy(buffer4GS, 256, buffer4GS, 0, 102144);
                                    Buffer.BlockCopy(Data_buf, 0, buffer4GS, 102144, 256);
                                }

                                Grayscale(buffer4GS);                               
                            }

                            
                    }
                    else if (MyDevice == null)
                    {
                        MessageBox.Show("ERROR. NODEVICE.", "Error Message");
                        break;
                    }
                }

CodePudding user response:

You could use Thread.Sleep()

int ms = 1;
Thread.Sleep(ms);

CodePudding user response:

Your Delay method gives the UI thread to handle events, by calling System.Windows.Forms.Application.DoEvents();

If you have an intensive operation bound to your UI thread (which explains the behaviour) you'll end up with a blocked UI. The usage of System.Windows.Forms.Application.DoEvents(); can resolve this, but it would be better to just execute your DOPPLER_NUM loop in another thread - not bothering the UI thread with it and keeping your program responsive.

Alternatively, you can just call System.Windows.Forms.Application.DoEvents(); from your loop itself and it would work just as good, maybe increasing performance a bit.

By the way:

Alternatives like Task.Delay and Thread.Sleep will not have a better accuracy as about 5ms. This is by design - because measuring the exact time will cost CPU power, same as the stopwatch does.

  • Related