【问题标题】:Dispatcher.Invoke to update UI ControlDispatcher.Invoke 更新 UI 控件
【发布时间】:2013-12-28 06:08:39
【问题描述】:

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

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

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

我正在尝试使 UI 控件 (WPF) 在StatusChanged 事件触发时更新为StatusChanged 字符串参数。我的理解是Dispatcher.Invoke 可以做到这一点,但我没有运气弄清楚如何从中拉出绳子。

基本上,我正在尝试获得相当于BackgroundWorker.ProgressChanged(使用ProgressChangedEventArgument.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
}

【问题讨论】:

  • 把字符串拉出什么?请展示您尝试过的内容 - 没有任何示例代码很难理解这个问题。
  • 我添加了代码来演示我正在尝试做的事情。
  • 但是你还没有展示你对Dispatcher.Invoke 的尝试——这正是我希望看到的,所以我们可以帮助你解决这个问题。
  • 就是这样的问题...我一直无法弄清楚如何使用 Dispatcher.Invoke 来完成这个。

标签: c# multithreading dispatcher


【解决方案1】:

使用 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>而不是@987654324 @。

上面的代码有点混乱,因为您使用一个委托订阅事件,然后将另一个传递给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);
}

【讨论】:

  • 太棒了!这正是我所需要的。太感谢了。我同意使用 String 很奇怪。这是一项需要在本周进行测试的紧急工作,所以我不得不牺牲优雅。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2010-12-11
  • 2014-10-14
相关资源
最近更新 更多