第一遍未由后台工作人员设置的变量

时间:2014-01-21 16:05:37

标签: c# multithreading events

我有一名背景工作者的观察员。让我们说观察者有以下结构:

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.",但是在之后的immediatley中,它会//Do Stuff调试显示RunWorkerCompleted事件触发两次。这仅在第一次更改扫描值时发生,之后所有更改都按预期工作。

问题:

1)为什么RunWorkerCompleted会发射两次?

2)为什么目标在RunWorkerCompleted的第一次火上没有更新

1 个答案:

答案 0 :(得分: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);
    }
}

最终,您可能希望使用BackgroundWorker更简单的解决方案替换ThreadPool。我建议这个:

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