2016-09-05 55 views
0

使用BackgroundWorker取消時出現問題,它只能使用一次。BackgroundWorker僅取消一次

第二次進入結束事件。

我是否需要在取消後使用:backgroundWorker.Dispose()?

這裏是我的代碼:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 

//some logic here before calling the copy method 

//copy folder method 
DirectoryCopy(source, destDirName, true,sender,e); 
} 

private void DirectoryCopy(string sourceDirName, string destDirName, object sender, DoWorkEventArgs e) 
{ 
    // Get the subdirectories for the specified directory. 
    DirectoryInfo dir = new DirectoryInfo(sourceDirName); 

    if (!dir.Exists) 
    { 
     throw new DirectoryNotFoundException(
      "Source directory does not exist or could not be found: " 
      + sourceDirName); 
    } 

    DirectoryInfo[] dirs = dir.GetDirectories(); 
    // If the destination directory doesn't exist, create it. 
    if (!Directory.Exists(destDirName)) 
    { 
     Directory.CreateDirectory(destDirName); 
    } 

    // Get the files in the directory and copy them to the new location. 
    FileInfo[] files = dir.GetFiles(); 

    foreach (FileInfo file in files) 
    { 
     Size += Math.Round(((double)file.Length/1048576), 2); 
     string temppath = System.IO.Path.Combine(destDirName, file.Name); 
     int buflen = 1024; 
     byte[] buf = new byte[buflen]; 
     using (FileStream sourceStream = new FileStream(file.FullName, FileMode.Open)) 
     { 
      using (FileStream destStream = new FileStream(temppath, FileMode.CreateNew)) 
      { 
       while (true) 
       { 
        if ((sender as BackgroundWorker).CancellationPending) 
        { 
         e.Cancel = true; 
         return; 
        } 
        //Progress Logic code 
       } 
      } 
     } 
     i++; 
    } 

    ////If copying subdirectories, copy them and their contents to new location. 
    if (copySubDirs) 
    { 
     // Copy Sub-Directories Logic 
    } 
} 
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (e.Cancelled) 
    { 
     MessageBox.Show("You cancel the copy!"); 
    } 

    else 
    { 
     MessageBox.Show("All the files were copied!"); 
    } 
    btnCopy.Visibility = Visibility.Visible; 
    btnCancel.Visibility = Visibility.Hidden; 
} 

private void btnCancel_Click(object sender, RoutedEventArgs e) 
{ 
    backgroundWorker1.CancelAsync(); 
} 

謝謝您的幫助。

回答

2

一旦BackgroundWorker完成,它不能重新啓動。調用Dispose()就是你應該做的,但它不會讓你重新啓動它。

您需要創建一個新的BackgroundWorker或使用更現代的async風格編程(如果您使用.Net 4.5或更高版本)。

+0

謝謝您的解釋。我像你說的那樣創建了一個新的BackgroundWorker,它可以工作。 – dadou

0

對@Matthew Watson答案進行了一些修正。

一旦BackgroundWorker已經完成,它將被重新啓動,您只需要正確地執行它。我已經做了很多次,並且一直工作。

(在某些情況下,一次又一次創建新的BackgroundWorkers是可取的,但要謹慎處理所使用的資源。如果您一次啓動多個工作者,則還應該注意線程池的侷限性,並且執行操作,例如從多個線程在驅動器上的文件執行操作simultinously實際上可以減緩你的應用下)

工作代碼使用相同的BackgroundWorker多次證明:

BackgroundWorker bg; 
    .... 
    // Constructor: create the worker (once): 
    bg = new BackgroundWorker(); 
    bg.WorkerSupportsCancellation = true; 
    bg.DoWork += new DoWorkEventHandler(bg_DoWork); 
    bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); 


    private void btnStartBgw_Click(object sender, EventArgs e) 
    { 
     if (!bg.IsBusy) 
      bg.RunWorkerAsync(); 
     else MessageBox.Show("The worker thread is busy!"); 
    } 

    void bg_DoWork(object sender, DoWorkEventArgs e) 
    { 
     this.DoWorkImpl((BackgroundWorker)sender, e); 
    } 

    private void DoWorkImpl(BackgroundWorker backgroundWorker, DoWorkEventArgs e) 
    { 
     for(int i=0;i<30;i++) 
     { 
      Thread.Sleep(1000); 
      if (backgroundWorker.CancellationPending) 
      { 
       e.Cancel = true; 
       return; 
      } 
     } 
    } 

    void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      MessageBox.Show("The work was canceled"); 
     } 
     else 
     { 
      MessageBox.Show("The work was completed successfuly"); 
     } 
    } 

    private void btnCancelBgw_Click(object sender, EventArgs e) 
    { 
     if (bg.IsBusy) bg.CancelAsync(); 
     else MessageBox.Show("The worker thread is not running!"); 
    } 

另外,我認爲你應該重新考慮拋出異常你的後臺線程。相反,您可以在e.Result中返回一些錯誤狀態。

0
BackgroundWorker _BackgroundWorker = new BackgroundWorker(); 

    public Form1() 
    { 
     InitializeComponent(); 
     _BackgroundWorker.DoWork += _BackgroundWorker_DoWork; 
     _BackgroundWorker.RunWorkerCompleted += _BackgroundWorker_RunWorkerCompleted; 
     _BackgroundWorker.ProgressChanged += _BackgroundWorker_ProgressChanged; 
     _BackgroundWorker.WorkerSupportsCancellation = true; 
    } 

    void _BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    void _BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    void _BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    private void btnStart_Click(object sender, EventArgs e) 
    { 
     _BackgroundWorker.RunWorkerAsync(e); 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     _BackgroundWorker.CancelAsync(); 
    } 
+0

使用此代碼_BackgroundWorker.WorkerSupportsCancellation = true; –