2015-12-08 47 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!"; 
      } 
     } 
相关问题