Hi,

I have a backgroundthread where I in this moment is using:

                while (runsomeCode == false)
                {
                    Thread.Sleep(1);
                }

to wait for "runsomeCode" will turn to: 'true' from another thread, which is button9_Click in this example.

However, using Thread.Sleep(1) doesn´t seem to be a very effective way.

I wonder if there could be any other method to wait inside the "while(true)" loop, for the variable "runsomeCode" to turn 'true'. When that happens, the code below will run once and the procedure starts from the beginning as seen in the code below.

        bool runsomeCode = false; bool backgroundthreadHasStarted = false;
        private void button9_Click(object sender, EventArgs e)
        {
            //Start the background worker thread
            if (backgroundthreadHasStarted == false)
            {
                Thread thread = new Thread(backgroundthread);
                thread.Start();
                backgroundthreadHasStarted = true;
            }

            runsomeCode = true;
        }
        public void backgroundthread()
        {
            while (true)
            {
                while (runsomeCode == false)
                {
                    Thread.Sleep(1);
                }
                runsomeCode = false; //Reset


                this.Invoke((MethodInvoker)delegate
                {
                    MessageBox.Show("Some code will run here!");
                });
            }
        }

Recommended Answers

All 13 Replies

Something like this?

public void backgroundthread()
{
    while (true)
    { // Forever, do...

        if(runsomeCode) { // Check for this necessary condition once per 10ms
            this.Invoke((MethodInvoker)delegate {
              runsomeCode = false; // Disable this one-off condition
              MessageBox.Show("Some code will run here!");
            }
        } // This sleep belongs to the parent loop.
        Thread.Sleep(10); // Wait.
    }
}

Thanks

I am trying to avoid using the Thread.Sleep() at all.

The thing is that I will need to react INSTANTLY when "runsomeCode" turns true.
That would be 1 millisecond or less without putting work to the CPU by waiting in a loop.

I have red about the "AutoResetEvent". But have never used it. I have tried to understand how it works.
I have tried to set up this example using this "AutoResetEvent".

This means practically that every time we press the button9_Click event. The messageBox will be shown.

It seems to work but wonder if this is set up correctly and if this is a good approach to do it?

        static AutoResetEvent objAuto = new AutoResetEvent(false);
        bool backgroundthreadHasStarted = false;
        private void button9_Click(object sender, EventArgs e)
        {
            //Start the background worker thread
            if (backgroundthreadHasStarted == false)
            {
                Thread thread = new Thread(backgroundthread);
                thread.Start();
                backgroundthreadHasStarted = true;
            }

            //Release the Wait
            objAuto.Set();
        }
        public void backgroundthread()
        {
            while (true)
            {
                //Wait
                objAuto.WaitOne();


                this.Invoke((MethodInvoker)delegate
                {
                    MessageBox.Show("Some code will run here!");
                });
            }
        }

Exactly, good job.
However, I don't see how the message box can be conditional in that case.
Perhaps the auto object accepts function delegates?

You only need to spawn the background thread once (your while loop will keep it running). I realise this is what your code actually does (thanks to the if statement) but you can tidy that up into a dedicated initialisation method.

The button click event should only call Set on the Mutex.

    static AutoResetEvent objAuto = new AutoResetEvent(false);
    bool backgroundthreadHasStarted = false;

    private void Initialise()
    {
        //Start the background worker thread
        if (backgroundthreadHasStarted == false)
        {
            Thread thread = new Thread(backgroundthread);
            thread.Start();
            backgroundthreadHasStarted = true;
        }
    }

    private void button9_Click(object sender, EventArgs e)
    {
        //Release the Wait
        objAuto.Set();
    }
    public void backgroundthread()
    {
        while (true)
        {
            //Wait
            objAuto.WaitOne();


            this.Invoke((MethodInvoker)delegate
            {
                MessageBox.Show("Some code will run here!");
            });
        }
    }

Once the thread passes the WaitOne section the AutoResetEvent will then automatically block subsequent threads so no further intervention is necessary :)

Thanks, the AutoResetEvent is very useful and will be good for waiting mechanisms.
Yes it is a good idéa to start the background thread as you showed.

There will be an additional thing to my code where I am not exactly sure to get it water proof.
The actual scenario is that there is an internet event that gives randomly updates which will release the .WaitOne(); in the backgroundthread.

1000 things will be checked in the backgroundthread if have received an update.

Problem:
While checking 1000 things. We can receive an update(s). This means we need to check all 1000 things again.

I have tried to set this up using the variables: "updateIsNeeded" and "backgroundworkerIsInWaitMode"
to act correctly. However I am sure a lock(object) method must be used in somehow for all variables to SYNC.
The problem is that don´t think I can use a lock(object) where "objAuto.WaitOne();" is located inside as that will cause a deadlock?

I wonder how we can modify the below code to work for this scenario?

        static AutoResetEvent objAuto = new AutoResetEvent(false);
        bool updateIsNeeded = false; bool backgroundworkerIsInWaitMode = false;
        private void internetsendsupdatesEvent(object sender, EventArgs e)
        {

            //We receive randomly updates from internet here
            updateIsNeeded = true;


            //Must relase the .WaitOne()
            if (backgroundworkerIsInWaitMode == true)
            {
                objAuto.Set();
            }
        }
        public void backgroundthread()
        {
            while (true)
            {
                //Only wait if we are waiting for update
                if (updateIsNeeded == false)
                {
                    backgroundworkerIsInWaitMode = true;
                    objAuto.WaitOne();
                }

                //Reset
                backgroundworkerIsInWaitMode = false;
                updateIsNeeded = false;


                //Thousands things to check, when new update
                for (int i = 0; i < 1000; i++)
                {
                    //"Run Some code here could take a few seconds
                }
            }
        }

If these things only need to be checked when you receive an update, then an event is fine for that. If they need to be run synchronously then you need to wait. Why do you need to constantly check these thousands of things and what exactly are they?

What should happen is:

  1. You receive a signal from the internet to update X
  2. Fire the event for updating X
  3. Event runs code that updates X

If you received 10 signals to update 10 different things and these all need to be run synchronously then you will need to block. However, in this case, your thread should exit when it is done. You don't want to keep it hanging around.

You shouldn't use true/false flags to enable/disable thread waiting.

I struggle to comprehend what all these thousands of things you're checking are, or even why you'd need to block a thread for this.

A deadlock will occur when two objects are waiting on each other to progress before either one can progress.

Example:
Thread A waits on Mutex B that is currently held by Thread B.
Thread B waits on Mutex A that is currently held by Thread A.

Thread A cannot continue until Thread B releases Mutex B and Thread B cannot continue until Thread A releases Mutex A. This is a deadlock.

I thought you had already grasped this form, please reconsider your general pattern.

while(true)
{ // Forever...

  // Check each event flag
    // Really, you should use events
  if( CLICK_EVENT ) { /* ... */ };
  if( MOVE_EVENT ) { /* ... */ };
  // It checks them both without waiting
  // If the condition is met, it'll execute
  // It still continues this function when it has finished

  // Wait for 1ms
  Thread.Sleep(1); // This timer applies equally to all events registered here.
}

If you do this, you will achieve your goal.

What you really want is events, but as they say, "You can lead a horse to water...."

Thanks Ketsuekiame/Unimportant:
Unimportant: The solution you described is exactly the one I have implemented with the Thread.Sleep(1).

However, the new goal is to get rid of the Thread.Sleep() entirely and replace them with AutoResetEvent. Thread.Sleep(1) is pushing on the CPU which I try to avoid. At the same time I need to react INSTANTLY. Much to ask for, I know :)

(I refer to my last code snippet)
The loop with 1000 things are actually updates for stocks. So each time we get an update, we want to loop all 1000 stocks to take different actions. (All 1000 needs to loop each time).

  1. Now however if we are looping on the 504:th stock and we receive 3 new updates which for example belongs to indexes 12,13,14. Those will not be taken care of during this loop.

  2. This means that when our loop is ready, we will need to loop all 1000 again 1 time to catch on 12,13,14.

  3. Now when we are at the end of the loop again and we haven´t got any more updates. THIS is where I am trying to set the backgroundthread in a .WaitOne() state to wait for a new update again and everything starts over.

If the thread is constantly working, you could potentially:
A) Split the thread into multiple worker threads
B) Remove sleep altogether (It's busy anyway)
C) Use event listeners

I know I perheps should use events at best but I have a little dilemma. The loop that does 1000 things consists of about 600 pages of code and split up this will be the worst nightmare. Since I will need to start putting locks everywhere. I really will try to avoid this if possible?

However, I have tried an experiment which raise a question. As I have tried it this might actually work. But I am not completely familiar with the AutoResetEvent functionality so better to ask.

Possible solution:
In the below example for test purpose, "button9_Click" will act as the "internetsendsupdatesEvent".

  1. Clicking button9 will start background thread and be put in .WaitOne(). The .Set() will release and we will have the messageBox shown.

  2. 5 seconds will pass which simulates some work

  3. Loop will be put in .WaitOne().

What I have tested is to click button9 both ONCE and MULTIPLE times, WHILE the "5 seconds will pass which simulates some work" which is before the code comes to the .WaitOne() again.

What happens is that the MessageBox will be shown ONCE again in this scenario, even that the code hasn´t reached the .WaitOne() yet.

The question I have is that is it possible that some kind of Buffer is Set in .WaitOne() which is detected and causes the .WaitOne() to be relased automatically once again when reaching this line. It seems that this is the case?
If that is true, then this will actually solve the whole problem and it will work, also without using any locks.

        static AutoResetEvent objAuto = new AutoResetEvent(false); bool backgroundthreadHasStarted = false;
        private void button9_Click(object sender, EventArgs e) 
        {
            //Start the background worker thread        
            if (backgroundthreadHasStarted == false)      
            {         
                Thread thread = new Thread(backgroundthread);      
                thread.Start();        
                backgroundthreadHasStarted = true;      
            }

            //Relase .WaitOne();
            objAuto.Set();
        }

        public void backgroundthread()
        {
            while (true)
            {
                objAuto.WaitOne();


                //Thousands things to check, when new update
                this.Invoke((MethodInvoker)delegate
                {
                    MessageBox.Show("1000 things to do...");
                });
                for (int i = 0; i < 1000; i++)
                {
                    //"Simulate work here, example 5 seconds
                    Thread.Sleep(5);
                }
            }
        }

An autoresetevent will only block if the mutex is set to non-signalled. It will only reset to this state once a thread enters the mutex.

Therefor, if your thread is already beyond the mutex and you call Set, the mutex will remain open until the thread circles back around again.

Additionally, Thread.Sleep has exactly the opposite effect of what you describe. It will actually cause the thread to stop executing (reduce the CPU usage of this thread to 0%) for the duration. The reason you see so heavy CPU usage is because your Thread.Sleep call has such a small time period you may as well not call it. Your loop will execute again almost straight away, causing the CPU load you see.

When you enter the number in Thread.Sleep this is the number of milliseconds not seconds. To pause for five seconds, you would need to put Thread.Sleep(5000);

Yes Thread.Sleep(), I am very familiar with. Thread.Sleep(5) in my example is only to simulate some work for this test. I am not using it.

To be sure I understand this correct then:

An autoresetevent will only block if the mutex is set to non-signalled. It will only reset to this state once a thread enters the mutex.

Therefor, if your thread is already beyond the mutex and you call Set, the mutex will remain open until the thread circles back around again.

As described in my example, if the thread then is already beyond the mutex/.WaitOne() and .Set is called. An additonal loop is needed until it again comes to the .WaitOne().?

And for confirmation, then this method should work for the purpose to not miss any updates, as in a way the .Set() keeps track on when last time it was .Set() and it hasn´t been .Set(), then it will be correct when reaching .WaitOne()?

Correct

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.