2010-07-15 60 views
5

我有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); 
      } 

解決方案提供here似乎不是爲我工作怎麼一回事,因爲它適用於經常性操作(爲其創建後臺工作,我想)。我是否必須爲我的目的使用線程(中止和加入),因爲我應該爲用戶提供取消長時間運行的可能性?

需要您的建議。

在此先感謝。

回答

7

不能使用Backgroundworker.CancelAsync()取消長時間運行的I/O操作。像rifnl回答,DoWork必須檢查worker.CancellationPending並設置e.Cancel

但是你也不應該使用Thread.Abort()。它可能會破壞你的過程。

您需要的解決方案必須來自provider.Synchronize();莫名其妙。

PS:和catch { return; }是可怕的。刪除整個try/catch並讓Bgw處理異常。

+0

或者,如果有可能給出同步TimeOut值,則可以將同步置於 while(!e.CancellationPending) privider.Synchronize(TimeOut); //如果可能的話 循環,同時繼續你現在擁有的功能。 – greggorob64 2010-07-15 13:28:40

2

您必須在您的DoWork方法中檢查e.Cancel,該代碼片段中缺少該方法,但您必須將下載方法更改爲異步調用,您將調用方法並在兜風中等待答案。這是可能的,但它不會同時檢查取消標誌。

檢查您發佈的解決方案(3號線):

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(!e.Cancel) 
    { 
     // do something 
    } 

    _resetEvent.Set(); // signal that worker is done 
} 
+0

謝謝回覆!我理解你的觀點,但是我必須使用backgraound worker嗎?我可以使用異步操作(就像我最初那樣)並使用AutoResetEvent來取消... – Sharov 2010-07-15 12:42:33

+0

正如riffnl所說,'BackgroundWorker'支​​持取消。您不必使用'BackgroundWorker',但我建議將抽象中的* up *移動到Task中,而不是將抽象中的*下移*到異步委託。 – 2010-07-15 12:53:56

+0

@rifnl,這不是e.Cancel。 – 2010-07-15 13:04:19