Dispatcher.Invoke更新UI控件

时间:2013-12-10 16:06:06

标签: c# multithreading dispatcher

我有一个.Net 4.0类,它有一个自定义事件处理程序(StatusChanged)。我试图通过一个线程消耗这个类。我没有使用BackgroundWorker的奢侈,因为我使用的库不支持多线程单元状态。

StatusChanged委托中的一个参数是字符串。

在UI中,单击按钮可初始化使用我的类的线程。

我正在努力使它成为一个UI控件(WPF)在StatusChanged事件触发时更新为StatusChanged字符串参数。我的理解是Dispatcher.Invoke可以做到这一点,但我没有运气弄清楚如何将字符串拉出来。

基本上,我试图获得相当于BackgroundWorker.ProgressChangedProgressChangedEventArgument.UserState)。

这是一些缩小的代码,用于演示我的目标:

带有事件处理程序的类:

public class MyClass
{
    public event EventHandler StatusChanged;

    private void alertStatus(string message)
    {
        if(StatusChanged == null)
            return;
        this.StatusChanged(message, new EventArgs());
    }

    public void DoStuff()
    {
        ///Do Stuff 1
        alertStatus("Done with stuff #1");

        ///Do Stuff 2            
        alertStatus("Done with stuff #2");
    }
}

所以按钮的.Click事件会做这样的事情:

private void buttonClicked(object sender, EventArgs e)
{
    Thread t = new Thread(doWork);
    t.Start();
}

private void doWork()
{
    MyClass class = new MyClass();
    class.StatusChanged += ...
    class.DoStuff();
    ///As StatusChanged fires within MyClass, a UI Textbox would get updated
}

1 个答案:

答案 0 :(得分:2)

使用lambda表达式最简单:

private void doWork()
{
    // Name changed to avoid it being a keyword
    MyClass clazz = new MyClass();
    clazz.StatusChanged += (sender, args) => {
        string message = (string) sender; // This is odd
        Action action = () => textBox.Text = message;
        Dispatcher.Invoke(action);
    };
    clazz.DoStuff();
}

使用字符串作为事件的发送者是非常奇怪的 - 最好使用EventArgs的子类,并使其存储消息 - 然后使您的事件使用EventHandler<T>代替仅EventHandler

上面的代码有点令人困惑,因为你用一个委托订阅事件,然后将另一个委托给Dispatcher.Invoke - 因此两个lambda表达式(一个在另一个内)。您总是可以使用方法组,至少对于外部方法组:

private void doWork()
{
    // Name changed to avoid it being a keyword
    MyClass clazz = new MyClass();
    clazz.StatusChanged += HandleStatusChange;
    clazz.DoStuff();
}

private void HandleStatusChange(object sender, EventArgs e)
{
    string message = (string) sender; // This is odd
    Action action = () => textBox.Text = message;
    Dispatcher.Invoke(action);
}