表单中的单独工作线程

时间:2011-02-15 09:23:35

标签: c# winforms multithreading

我有一个Windows窗体应用程序,可以从各个地方获取一些数据。因此,我创建了一个获取和更新图形内容的线程(progressbar,textfields ++)。

但我有一些问题退出它,那个线程就是这样。它是这样的:

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

和循环功能

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

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

        Thread.Sleep(5000);    
    }
}

关闭窗口会使休息时间,但它现在被处理??

6 个答案:

答案 0 :(得分:2)

正如Johann建议您可能想要查看BackgroundWorker对象。但是,如果这是一个学习项目,你只想通过各种方式熟悉线程!

我建议添加一个新的volatile布尔变量,就像这样。

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

并在您的表单上添加OnClosing事件,您可以:

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

答案 1 :(得分:1)

一种简单的方法是定义您使用的bool参数而不是while(true)以及将其设置为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;
}

请记住,虽然线程停止仍然需要5秒钟(或者你的睡眠值设置的时间有多长)

注意:如果线程更新其他线程创建的任何控件,则需要使用'InvokeRequired'模式,请参阅:Automating the InvokeRequired code pattern

答案 2 :(得分:1)

在这种情况下,我经常使用AutoResetEvent在循环内等待,并与提供调用者的方法配对,以指示应取消线程操作。您可以使用AutoResetEvent.WaitOne中的返回值并将其用作取消标记(如果true被调用则返回Set,如果超时则返回false ):

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();
}

答案 3 :(得分:0)

使用BackgroundWorker对象可能更容易。它还支持取消并具有内置的进度报告功能。

答案 4 :(得分:0)

我会使用线程的静态成员来启动线程的控制停止并在表单中添加如下所示的卸载:

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

在线程中你必须做这样的事情:

if(stopToDo)
{
    return;
}

答案 5 :(得分:0)

如果您只想在主线程(可能是您的GUI线程)退出时退出新线程,则可以将新线程作为后台线程:

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