1

我有具有 UI 和后台线程的 c# 应用程序。根据用户输入,我喜欢停止和启动后台线程。如我所见,我在这里有两个选择:

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");
    }
4

2 回答 2

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";
}
于 2009-12-22T20:04:29.523 回答
0

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

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

于 2009-12-22T20:07:52.420 回答