user186246
user186246

Reputation: 1877

Multithreading in windows forms C#

In a windows application, apart from main thread there is another thread which does a long run operation for every minute and updates the UI using Invoke method.

How can we terminate the another thread gracefully when it is in sleeping state?

Is it a right choice of using sleep here?

Upvotes: 0

Views: 422

Answers (4)

Nikola Radosavljević
Nikola Radosavljević

Reputation: 6911

There is no such thing as graceful thread termination. Instead, your thread should be instructed to stop doing it's job once it's no longer needed. You could do this by creating class to hold worker thread parameters inside which you store information whether work should be stopped, and pass an object of that class to the thread.

public class WorkerParams
{
    public bool Stop = false;
}

private void TestForm_Load(object sender, EventArgs e)
{
    _thread = new Thread(lonRunThread);
    _thread.Start(new WorkerParams());
}

public void lonRunThread(object argument)
{
    WorkerParams param = argument as WorkerParams;
    DateTime lastExec = DateTime.MinValue;
    while(!param.Stop)
    {
        if (new TimeSpan(DateTime.Now.Ticks - lastExec.Ticks).TotalSeconds >= 60)
        {
            Operation1();
            Invoke(new UpdateDelegate(updateState));
            Operation2();
            Invoke(new UpdateDelegate(updateState));
            lastExec = DateTime.Now;
        }
        Thread.Sleep(500);
    }
}

Upvotes: 0

Adam Houldsworth
Adam Houldsworth

Reputation: 64487

Instead of making the thread once and then terminating, perhaps use a form timer to trigger a background worker thread every 60000 milliseconds? You then don't need to sleep the background thread at all.

This means you only need to stop the timer to stop more background tasks from being spawned, but obviously this doesn't stop any currently active background thread.

Threads should very rarely be aborted, as there isn't any great mechanism available for doing it with any consistency. There are various guards such as critical code markers. However, I think it's best to have the long running code poll for cancellation, then you can code your own logic for abandoning ship and returning early. Note, this is not the same as aborting a thread forcefully.

I don't think sleep is the right choice in almost any circumstances.

For example:

private bool _askedToCancel;

public void lonRunThread()
{
    if (!_askedToCancel)
    {
        Operation1();
        Invoke(new UpdateDelegate(updateState));
    }

    if (!_askedToCancel)
    {    
        Operation2();
        Invoke(new UpdateDelegate(updateState));
    }
}

Seems a little messy, however you retain very good control over what logic is performed if you refuse to abort threads forcefully and instead use the cancellation approach.

Because this isn't critical code, and because actions on booleans are atomic, you should be safe having both threads talk to the bool without any locking. And even if it's not truly safe, the only result is some more work is done.

Upvotes: 4

Yannis
Yannis

Reputation: 6157

I would change the while(true) in longRunThread method and make it

while (_RunLongThread)

then in the TestForm I would declare the private Boolean _RunLongThread = true and set it to false from whichever method needs to stop the long running thread.

Thats a "graceful" way of stopping it i.e. waiting to complete its current task and then terminates

Upvotes: 0

Carl Winder
Carl Winder

Reputation: 948

You can always set the thread to be a background thread, that way when the application exits the thread will automagically be stopped.

When do you want the thread to be stopped?

If you want it stopped in mid-operation a boolean flag would be appropriate.

So instead of

while(true)

You would do something like

while(exit == false)

Upvotes: 1

Related Questions