开发者

Separate Worker Thread in Forms

开发者 https://www.devze.com 2023-02-11 15:44 出处:网络
I\'ve got a Windows Forms Application that does some data fetching from various places. Because of this I\'ve made a thread that fetches and updates the graphical stuff (progressbar, textfields++).

I've got a Windows Forms Application that does some data fetching from various places. Because of this I've made a thread that fetches and updates the graphical stuff (progressbar, textfields++).

But I'm having some problems quitting it, the thread that is. It goes something like this:

Thread t = new Thread(new ThreadStart(this.Loop))
t.Start();

and the Loop function

void Loop
{
    while(true)
 开发者_如何转开发   {
        if( parent window isDisposed )
        break;

        /*
        fetch and update stuff goes in here...
        */

        Thread.Sleep(5000);    
    }
}

Closing the window will make the while break, but it is now disposed??


As Johann has suggested you might want to look at BackgroundWorker object. However if this is a learning project and you'd just like to familiarize yourself about threads then by all means!

What I'd suggest is adding a new volatile boolean variable, something like this.

volatile bool CancelationPending = false;
...
Thread T = new Thread(new ThreadStart(method));
CancelationPending = false;
...
void method () {
    while (!CancelationPending)
    {
        /* do stuff*/
    }
}

and on your Form you can add OnClosing event in which you can:

private void OnClosing(object sender, EventArgs e)
{
    CancelationPending = true;
}


In such scenarios I often use an AutoResetEvent for waiting inside the loop, paired with a method offering the caller to indicate that the threaded operation should be cancelled. You can make use of the return value in AutoResetEvent.WaitOne and use that as a cancel flag in itself (it returns true if it Set is called, false if it times out):

private AutoResetEvent waitHandle = new AutoResetEvent(false);

void Loop()
{
    while(true)
    {
        /*
        fetch and update stuff goes in here...
        */

        if (waitHandle.WaitOne(5000))
        {
            break;
        }
    }
}

public void Cancel()
{
    waitHandle.Set();
}


One simple way is to define a bool parameter that you use instead of while(true) and a method to set it to false:

bool threadRunning = false;

Thread t = new Thread(new ThreadStart(this.Loop));
threadRunning = true;
t.Start();


void Loop()
{
    while(threadRunning)
    {
        if( parent window isDisposed )
        break;

        /*
        fetch and update stuff goes in here...
        */

        Thread.Sleep(5000);    
    }
}

public void stopThread() 
{ 
    threadRunning = false;
}

Bear in mind though it can still take up to 5 seconds for the thread to stop (or however long your sleep value is set for)

Note: you will need to use the 'InvokeRequired' pattern if the thread updates any controls created by other threads, see: Automating the InvokeRequired code pattern


It may be easier for you to use a BackgroundWorker object. It also supports cancellation and has built-in progress reporting capabilities.


I would use a static member of the thread to initiate a controled stop of the thread and add in the form's unload something like this:

        stopToDo = true;
        while (todoThread.IsAlive)
        {
            System.Threading.Thread.Sleep(10);
        }

in the thread you have to do something like this:

if(stopToDo)
{
    return;
}


If you just want your new thread to exit when the main thread (probably your GUI thread) exits, you can make your new thread a background thread:

Thread t = new Thread(new ThreadStart(this.Loop));
t.IsBackground = true;
t.Start(); 
0

精彩评论

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