我的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");
}
提前感谢您的帮助。
答案 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更好。
另一种解决方案是从线程类继承,并向此类添加一个停止或暂停线程的函数。这样您就可以隐藏实现的细节。