取消后台工作者

我有UI显示长时间运行的状态(从ftp下载一些文本文件)。 为了我的目的,我使用backgroundworker,我无法取消操作。

void worker_DoWork( object sender, DoWorkEventArgs e ) { try { int rowIndex = (int)e.Argument; //begin UI update StartWaitingBar(rowIndex); //get provider id cell GridViewDataRowInfo row = _proivderGridView.Rows[rowIndex]; GridViewCellInfo provIdCell = row.Cells[ "ProviderId" ]; var providerData = GetProviderData(Convert.ToInt32( provIdCell.Value)); var provider = ProviderFactory.CreateProvider(providerData); provider.Synchronize(); e.Result = rowIndex; } catch (Exception exception) { return; } } 

和创建工人的代码:

  BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += worker_DoWork; worker.RunWorkerCompleted += worker_RunWorkerCompleted; worker.WorkerSupportsCancellation = true; worker.RunWorkerAsync(args.RowIndex); _syncWorkers.Add(providerId,worker); ... var worker = _syncWorkers[providerId]; if(worker.IsBusy) { worker.CancelAsync(); } else { worker.RunWorkerAsync(args.RowIndex); } 

这里提供的解决方案对我来说似乎不起作用,因为它适用于重复操作(我想这是为后台工作者创建的)。 为了我的目的,我是否必须使用线程(中止和连接),因为我应该为用户提供取消长时间运行的可能性?

需要你的建议。

提前致谢。

您不能使用Backgroundworker.CancelAsync()来取消长时间运行的I / O操作。 像rifnl回答的那样,DoWork必须检查worker.CancellationPending并设置e.Cancel

但是你也不应该使用Thread.Abort() 。 它可能会破坏你的过程。

您需要的解决方案必须来自provider.Synchronize(); 不知何故。

PS:并catch { return; } 太可怕了。 删除整个try / catch并让Bgw处理exception。

你必须在你的DoWork方法中检查e.Cancel,这在你的代码片段中是遗漏的,但你必须将你的下载方法更改为异步调用,你正在调用方法并等待答案在dowork里面。 这是可能的,但它不会同时检查取消标志。

检查您发布的解决方案(第3行):

 void worker_DoWork(object sender, DoWorkEventArgs e) { while(!e.Cancel) { // do something } _resetEvent.Set(); // signal that worker is done }