2013-12-12 145 views
4

我正在努力與線程。 問題是當我迭代通過foreach循環。暫停新的BackGroundWorker,直到完成前

設置爲this.Document時,應用程序執行登錄,該操作由事件觸發並需要幾秒鐘才能完成。在worker_RunWorkerCompleted方法中,我需要執行一些依賴於當前登錄信息的操作。

問題是,在我可以對第一個文件執行此操作之前,this.Document已經更改,使應用程序執行另一次登錄。這樣我永遠無法真正執行我的行動。

我的問題是:如何暫停下一個線程,直到前一個線程完成。 有沒有其他解決方案來解決我的問題?我試過AutoResetEvent但我沒有運氣。我在RunWorkerAsync調用後設置了waitOne(),在RunWorkerCompleted中設置了.Set()。該代碼永遠不會獲取RunWorkerCompleted ...

下面是代碼:

public void Start(object obj) 
    { 
     try 
     { 
      foreach (KeyValuePair<string, Stream> pair in this.CollectionOfFiles) 
      { 
       Worker = new BackgroundWorker(); 
       Worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
       Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 

      using (Stream stream = pair.Value) 
       { 
       primaryDocument = new Document(stream); 

       DataHolderClass dataHolder = new DataHolderClass(); 
       dataHolder.FileName = pair.Key; 
       dataHolder.Doc = secondaryDocument; 

       //background thread call 
       Worker.RunWorkerAsync(dataHolder); 
       } 
      } 
      } 

     catch (Exception ex) 
     { 
      // exception logic 
} 
     finally 
     { 
      // complete logic 
     } 
    } 


    private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     DataHolderClass dataHolder = ((DataHolderClass)e.Argument); 
     // setting this attribute triggers execution of login event 
     this.Document = dataHolder.Doc; 
     e.Result = (dataHolder); 
    } 


    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // here I need to perform some actions that are depending on the current login 
     DataHolderClass dataHolder = ((DataHolderClass)e.Result); 
     this.eventAggregator.GetEvent<ActionEvent>().Publish(new Message(EMessageType.Info) { Title = dataHolder.FileName }); 
    } 
+0

當Worker.RunWorkerAsync(dataHolder);再次被擊中... – no9

+0

我得到這個權利嗎?設置文檔觸發器以某種方式啓動? – gwiazdorrr

+0

不...設置文檔觸發器登錄操作(此處未顯示)。當我在worker_RunWorkerCompleted時,我需要做一些檢查登錄的操作。登錄需要幾秒鐘的時間才能完成以及基於事件的呼叫。我的情況是,當我到達worker_RunWorkerCompleted時,登錄已經發生變化,因爲集合中的另一個項目設置了這個文檔。 – no9

回答

0

NO9,

嘗試以下操作:

System.Threading.ManualResetEvent _busy = new System.Threading.ManualResetEvent(false); 

void ResumeWorker() 
{ 
    // Start the worker if it isn't running 
    if (!backgroundWorker1.IsBusy) backgroundWorker1.RunWorkerAsync(dataHolder); 
    // Unblock the worker 
    _busy.Set(); 
} 

void PauseWorker() 
{ 
    // Block the worker 
    _busy.Reset(); 
} 

void CancelWorker() 
{ 
    if (backgroundWorker1.IsBusy) { 
     // Set CancellationPending property to true 
     backgroundWorker1.CancelAsync(); 
     // Unblock worker so it can see that 
     _busy.Set(); 
    } 
} 

然後在你的代碼運行的方法。

讓我知道,如果它的工作原理:)

0
class SimpleWaitPulse 
{ 
    static readonly object _locker = new object(); 
    static bool _go; 

    static void Main() 
    {        // The new thread will block 
    new Thread (Work).Start();  // because _go==false. 

    Console.ReadLine();   // Wait for user to hit Enter 

    lock (_locker)     // Let's now wake up the thread by 
    {        // setting _go=true and pulsing. 
     _go = true; 
     Monitor.Pulse (_locker); 
    } 
    } 

    static void Work() 
    { 
    lock (_locker) 
     while (!_go) 
     Monitor.Wait (_locker); // Lock is released while we’re waiting 

    Console.WriteLine ("Woken!!!"); 
    } 
} 

可使用脈衝? 來自Threading in C# from albahari.com

0

好,設計是可怕的......但如果需要堅持下去,你可以設置等待句柄在以前的工人,等待它的下一次。這是最小的修復,仍然相當可憎:

public void Start(object obj) 
{ 
    try 
    { 
     BackgroundWorker previousWorker = null; 
     DataHolderClass previousWorkerParams = null; 

     foreach (KeyValuePair<string, Stream> pair in this.CollectionOfFiles) 
     { 
      // signal event on previous worker RunWorkerCompleted event 
      AutoResetEvent waitUntilCompleted = null; 
      if (previousWorker != null) 
      { 
       waitUntilCompleted = new AutoResetEvent(false); 
       previousWorker.RunWorkerCompleted += (o, e) => waitUntilCompleted.Set(); 

       // start the previous worker 
       previousWorker.RunWorkerAsync(previousWorkerParams); 
      } 

      Worker = new BackgroundWorker(); 

      Worker.DoWork += (o, e) => 
      { 
       // wait for the handle, if there is anything to wait for 
       if (waitUntilCompleted != null) 
       { 
        waitUntilCompleted.WaitOne(); 
        waitUntilCompleted.Dispose(); 
       } 
       worker_DoWork(o, e); 
      }; 

      using (Stream stream = pair.Value) 
      { 
       primaryDocument = new Document(stream); 

       DataHolderClass dataHolder = new DataHolderClass(); 
       dataHolder.FileName = pair.Key; 
       dataHolder.Doc = secondaryDocument; 

       // defer running this worker; we don't want it to finish 
       // before adding additional completed handler 
       previousWorkerParams = dataHolder; 
      } 

      previousWorker = Worker; 
     } 

     if (previousWorker != null) 
     { 
      previousWorker.RunWorkerAsync(previousWorkerParams); 
     } 
    } 

    catch (Exception ex) 
    { 
     // exception logic 
    } 
    finally 
    { 
     // complete logic 
    } 
} 
相關問題