2011-02-15 72 views
0

我有一個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);  
    } 
} 

關閉窗口將令而破,但現在配置?

回答

2

正如約翰建議你可能想看看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; 
} 
0

您可能更容易使用BackgroundWorker對象。它還支持取消,並具有內置的進度報告功能。

+0

拖放邏輯對象....哼哼 – 2011-02-15 09:31:10

+0

@Aaron Gage:你在這裏有什麼意思? – 2011-02-15 09:37:47

+0

那麼,你還會喜歡拖放循環嗎? – 2011-02-15 11:31:37

1

一個簡單的方法是定義你使用一段時間(真),而不是一個布爾參數,將其設置爲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

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

我會使用的靜態成員線程啓動線程的controled停止,並添加在窗體的卸載是這樣的:你必須做這樣的事情線程

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

if(stopToDo) 
{ 
    return; 
} 
0

如果你只是想你的新線程退出時,主線程(可能是您的GUI線程)退出,你可以讓你的新線程成爲後臺線程:

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