2015-12-08 55 views
3

我有一個關於使用線程的問題。我在WinForms中有一個應用程序。我有一個方法的開始按鈕。當我點擊它時,該方法開始執行並持續很長時間。當方法執行時,表單不活動,直到方法結束才能關閉它。我想讓表格激活並點擊另一個按鈕(停止按鈕)來停止執行方法。如何在WinForms C#中使用線程?

private void start_Click(object sender, EventArgs e) 
    { 
     StartLoading() //Some Method which performing I want to stop at any time 
    } 

    private void stop_Click(object sender, EventArgs e) 
    { 
     //Stop performing Method from start_Click 
    } 

我tryed使用下面的代碼:

private void start_Click(object sender, EventArgs e) 
    { 
     Thread StartThread = new Thread(StartLoading); 
     StartThread.Start(); 
    } 

    public void StartLoading() 
    { 
    } 

和它的作品。該方法在表單保持活動時執行。但我不知道如何在stop_Click事件中停止此線程。 Maye有另一種方式來做我想要的?

問候 謝爾蓋

+0

StartThread.Abort(); – Behzad

回答

2

如果你正在做的線程裏面的一些循環,我會建議你添加一個變量,就像這樣:

在你停止按鈕,添加如下:

bool isStopped = false; 

而且你的循環中:

while(yourCondition) 
{ 
    if(isStopped) 
     break; 
} 

這樣,它的安全,並能確保你完成當前循環

但是,如果你想立即終止它,有一個名爲函數Thread.Abort()

你必須要修改這樣的代碼:

Thread StartThread = null; 
private void start_Click(object sender, EventArgs e) 
{ 
    StartThread = new Thread(StartLoading); 
    StartThread.Start(); 
} 

public void StartLoading() 
{ 
    StartThread.Abort(); 
} 
+1

注意,調用'StartThread.Abort()'會引發一個例外,應該被抓。 –

+1

謝謝。你的答案有效。這很簡單,很簡單。所有其他的答案是太難理解我)) – Sergey

+2

@Sergey'Thread.Abort的()'[是一個可怕的選擇(http://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread -abort),它可能會使程序處於損壞狀態。不要這樣做。 –

4

如果你想,直到它完成或將要執行的行動緩慢,直到您手動取消它,你可能需要使用TaskCancellationToken。對我來說,這似乎是最合適的方式:

public class MyForm 
{ 
    private CancellationTokenSource cts = new CancellationTokenSource(); 
    private Task task; 

    private void buttonStart_Click(object sender, EventArgs e) 
    { 
     buttonStart.Enabled = false; 
     buttonCancel.Enabled = true; 

     task = Task.Factory.StartNew(() => { 
      // do something extremely slow 
      // and use 'ThrowIfCancellationRequested' 

      for (int i = 0; i < Int32.MaxValue; i++) 
      { 
       Thread.Sleep(10); 
       cts.Token.ThrowIfCancellationRequested(); 
      } 
     }, cts.Token).ContinueWith(t => { 
      if (t.IsCanceled) 
      { 
       // User has cancelled loading 
      } 
      if (t.IsFaulted) 
      { 
       // Exception has occured during loading 
      } 
      if (t.IsCompleted) 
      { 
       // Loading complete 
      } 
     }); 
    }  

    private void buttonCancel_Click(object sender, EventArgs e) 
    { 
     buttonStart.Enabled = true; 
     buttonCancel.Enabled = false; 

     cts.Cancel(); 
    } 
} 
+0

我認爲你需要使用'cts.Token.ThrowIfCancellationRequested()''沒有如果(cts.IsCancellationRequested)回報;'如果你想't.IsCanceled',如果你取消任務啓動後返回true。如果你不認爲取消是被請求的,但是方法完成了,它就會工作,所以它將它標記爲「IsCompleted」。 –

+0

@ScottChamberlain當然,你是對的。我編輯了我的答案。我是否在某處丟失了'try .. catch'或是否會正確處理'OperationCanceledException'本身?謝謝。 –

+0

如果OperationCanceledException與作爲「StartNew」的第二個參數傳入的相同標記關聯,則它被視爲特殊情況並進入IsCanceled狀態而不是IsFaulted狀態。如果引發OperationCanceledException,但它與傳入的令牌沒有關聯,它將顯示爲一個有故障的任務。 –

1

您可以使用BackgroundWorker這個。

 private BackgroundWorker bw = new BackgroundWorker(); 

     public Form() 
     { 
      InitializeComponent(); 

      bw.WorkerSupportsCancellation = true; 
      bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     } 

     private void start_Click(object sender, EventArgs e) 
     { 
      if (!bw.IsBusy) 
      { 
       bw.RunWorkerAsync(); 
      } 
     } 
     private void stop_Click(object sender, EventArgs e) 
     { 
      if (bw.WorkerSupportsCancellation) 
      { 
       bw.CancelAsync(); 
      } 
     } 
     private void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

      if (worker.CancellationPending) 
      { 
       e.Cancel = true; 
       return; 
      } 

      StartLoading(); //Some Method which performing I want to stop at any time 
     } 
     private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Cancelled) 
      { 
       //"Canceled!"; 
      } 

      else if (e.Error != null) 
      { 
       //"Error: " + e.Error.Message); 
      } 

      else 
      { 
       //"Done!"; 
      } 
     } 
相關問題