2014-01-21 33 views
0

我有一個後臺工作人員的觀察員。假設觀察者具有以下結構:第一次通過後臺工作人員設置的變量

internal class Observer 
{ 
    private readonly BackgroundWorker bw1; 
    internal Object target; 

    public Observer() 
    { 
     bw1 = new BackgroundWorker(); 
     bw1.DoWork += bw1_DoWork; 
     bw1.RunWorkerCompleted += bw1_RunWorkerCompleted; 
     bw1.WorkerSupportsCancellation = true; 

    } 


    private void bw1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     e.Result = new object(); // Query to database 
    } 

    private void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     target = e.Result as object; 

     if (ChangedScannedValue != null) 
     { 
      ChangedScannedValue(_scannedValue); 
     } 
    } 


    private String _scannedValue = string.Empty; 
    internal delegate void OnChangedScannedValue(String scannedValue); 
    internal event OnChangedScannedValue ChangedScannedValue; 
    internal String ScannedValue 
    { 
     get { return _scannedValue; } 
     set 
     { 
      _scannedValue = value; 
      bw1.RunWorkerAsync(_scannedValue); 
      //ProcessScannedValue(); 

     } 
    } 
} 

我有另一個聽該事件的類。

public partial class myControl : UserControl 
{ 
    Observer _observer = new Observer(); 

    public myControl() 
    { 
     InitializeComponent(); 
    } 

    internal void LoadData(Observer observer) 
    { 
     _observer = observer; 
     _observer.ChangedScannedValue += _observer_ChangedScannedValue; 
    } 

    void _observer_ChangedScannedValue(string ScannedValue) 
    { 
     if (_observer.target != null) 
     { 
      // Do Stuff 
     } 
     else 
     { 
      MessageBox.Show("NO TARGET FOUND."); 
     } 
    } 
} 

事情是。最初,在後臺工作完成後,我收到消息框"NO TARGET FOUND.",然而,立即執行//Do Stuff調試顯示RunWorkerCompleted事件觸發兩次。這隻會在第一次更改掃描值時發生,所有更改都會按照需要進行。

問題:

1)爲什麼RunWorkerCompleted火兩次?

2)爲什麼不更新的RunWorkerCompleted

+1

在屬性setter中運行BackgroundWorker只是似乎是錯誤的。 – LarsTech

+0

非常非常錯誤。 – rae1

+0

我這樣做是爲了避免UI被鎖住。當設置掃描值時,我需要從與該值關聯的數據庫加載數據並顯示它。我應該如何去改變它 – Oxymoron

回答

1

的第一把火目標,您可以用target嘗試再次bw1_DoWork設定已,即:

private void bw1_DoWork(object sender, DoWorkEventArgs e) { 
    target = new object(); // Query to database 
} 

private void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
    if (ChangedScannedValue != null) { 
     ChangedScannedValue(_scannedValue); 
    } 
} 

最終,你可能想用ThreadPool更簡單的解決方案替換BackgroundWorker。我建議這樣做:

internal String ScannedValue { 
    get { return _scannedValue; } 
    set { 
     _scannedValue = value; 
     ThreadPool.QueueUserWorkItem((WaitCallback) delegate { 
      target = new object(); // query database 
      if (ChangedScannedValue != null) ChangedScannedValue(_scannedValue); 
     }); 
    } 
}