2014-01-21 87 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); 
     }); 
    } 
}