如何一遍又一遍地启动和停止后台线程?

时间:2009-12-22 19:20:31

标签: c# multithreading background restart

我的c#app有UI和后台线程。根据用户输入我喜欢停止并启动后台线程。我看到这里有两个选择:

1)完全停止然后启动后台线程作为新线程(我无法做到这一点。我一直得到我的流程结束消息)

2)暂停后台线程,直到用户再次点击运行。

这是我在bw.CancelAsync();

之后再次调用的代码
    private void StartBackgroundWorker()
    {
        bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += bw_DoWork;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;
        bw.RunWorkerAsync("Background Worker");
    }

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

你无法启动和停止这样的后台工作者,但是在你的DoWork事件中,你可以让它询问它是应该执行还是等待。

你也可以继承BackgroundWorker(覆盖OnDoWork()方法),并为其添加切换私有等待句柄的开始/暂停方法,这比让你的UI了解ManualResetEvent要好得多。

//using System.Threading;

//the worker will ask this if it can run
ManualResetEvent wh = new ManualResetEvent(false);

//this holds UI state for the start/stop button
bool canRun = false;

private void StartBackgroundWorker()
{
    bw = new BackgroundWorker();
    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += bw_DoWork;
    bw.RunWorkerCompleted += bw_RunWorkerCompleted;
    bw.RunWorkerAsync("Background Worker");
}


void bw_DoWork(object sender, DoWorkEventArgs e)
{
     while(true) 
     {
          //it waits here until someone calls Set() on wh  (via user input)
          // it will pass every time after that after Set is called until Reset() is called
          wh.WaitOne()

         //do your work

     }
}


//background worker can't start until Set() is called on wh
void btnStartStop_Clicked(object sender, EventArgs e)
{
    //toggle the wait handle based on state
    if(canRun)
    {
        wh.Reset();
    }
    else {wh.Set();}

    canRun= !canRun;
    //btnStartStop.Text = canRun ? "Stop" : "Start";
}

答案 1 :(得分:0)

您可以随时中止线程并捕获ThreadAbortedException。我不确定这是否是最简洁的解决方案,因为异常会导致大量开销,但我认为这比在Dan建议的代码中传播WaitOne更好。

另一种解决方案是从线程类继承,并向此类添加一个停止或暂停线程的函数。这样您就可以隐藏实现的细节。