开发者

C# - How do I Wake a Sleeping thread?

I was able to solve this myself by reading a bit further, I was asuming that you should refer to Threads rather than to objects. It works now. :)

Original post:


I've looked into most of the similar questions, and I've seen a lot of answers containing monitors, pulses and etc. however I can't make it work.

I'm rather new to C#, so if I'm using threading wrong please forgive me. But my problem is as follows;

I have 4 threads, one of which reduces an integer in a column in three different tables by one. Then 3 different threads which performs an action depending on whether or whether not any of the values reached zero.

What I want to do is have the Thread counting down only awaken the correct thread of the three others if something reaches zero. To check for this is not a problem, t开发者_运维知识库he problem is to wake the threads. I do currently have a working one where they all just run at once, but I want to use this in order to make it efficient.

Here is the code I use, I've only included one for simplicity, and it's the same idea. Is this how I should use it?

It's what I got from reading the examples and results on google.

public class UpdateQueueSuggestion

{

public void startGame()
{      
    Thread Check = new Thread(new ThreadStart(checkUpdate));
    Check.Start();
}

public void checkUpdate()
{
    // (...) Some intialization of variables

    // Create the thread used for when entries in the Queue table reaches 0.
    Thread Build = new Thread(new ThreadStart(performBuildingUpdate));
    Build.Start();

    // Some sqlcommands.

    while (true)
    {
        try
        {
            // Enter to synchronize, if not it yields
            // Object synchronization method was called from an unsynchronized block of code.
            Monitor.Enter(this);
            connection.Open();

            // Execute commands. Get COUNT(*) for results reaching 0 in tables and save int in i.

            if (i > 0)
            {
            // Pulse the thread called Build, in order to wake it again.
                Monitor.Pulse(Build);
            }
        }

        finally
        {
            // Exit monitor.
            Monitor.Exit(this);
            connection.Close();
        }
        // This one is supposed to run each second, decrement and check for zeros.
        // Works just fine if I just put everything in here without monitors,
        // but as I said I want to split it up for efficiency.
        Thread.Sleep(1000);
    }

}

public void performBuildingUpdate()
{
    // Some sqlcommands

    while (true)
    {
        Monitor.Enter(this);
        try
        {
            connection.Open();
            // Execute commands.
        }

        finally
        {
            connection.Close();
            Monitor.Wait(this);
            Monitor.Exit(this);
        }
    }

}

}

Any help is greatly appreciated, thanks.

If anyone wonders, it's for a browser game project we're making for a C# class at school. This is supposed to take the approximate time for game events. Currently we're running with all the commands in one thread and running it every 10 seconds. Would be great to make it able to run every second.


The most straight-forward way to do this would be to have three separate lock objects, each worker thread would wait on a specific lock, and the controlling thread would pulse the correct lock based on the decremented values.

public class Controller
{
    private object _lock1;
    private object _lock2;
    private object _lock3;

    private Thread _worker1;
    private Thread _worker2;
    private Thread _worker3;


    public Controller()
    {
        _lock1 = new object();
        _lock2 = new object();
        _lock3 = new object();

        _worker1 = new Thread(ExecuteWorker, _lock1);
        _worker2 = new Thread(ExecuteWorker, _lock2);
        _worker3 = new Thread(ExecuteWorker, _lock3);

        lock (_lock1)
        {
            _worker1.Start();
            Monitor.Wait(_lock1);
        }
        lock (_lock2)
        {
            _worker2.Start();
            Monitor.Wait(_lock2);
        }
        lock (_lock3)
        {
            _worker3.Start();
            Monitor.Wait(_lock3);
        }
    }

    public void Execute()
    {
        // Perform database logic, assuming decremented values are stored.
        int value1 = DecrementValueFromDB();
        int value2 = DecrementValueFromDB();
        int value3 = DecrementValueFromDB();

        if (value1 == 0)
        {
            lock (_lock1)
            {
                Monitor.Pulse(_lock1);
            }
        }

        if (value2 == 0)
        {
            lock (_lock2)
            {
                Monitor.Pulse(_lock2);
            }
        }

        /// ... repeat for third value
        //
    }
}

Each worker is running something like:

static void ExecuteWorker(object lockObject)
{
    lock (lockObject)
    {
        // Signal to thread creator that the thread is running.
        Montior.Pulse(lockObject);

        // Keep running while we have not been marked to shut down
        while (!complete)
        {
            Monitor.Wait(lockObject);
            // logic to execute when signaled (value == 0)
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜