【问题标题】:WPF: refresh a controls in other threadWPF:刷新其他线程中的控件
【发布时间】:2013-01-02 16:02:16
【问题描述】:

我有一个使用线程的简单 WPF 应用程序。例如。在新线程中,我得到 DateTime,我想将它返回到主线程中的 TextBox。我读到这样做我必须使用 ControlDispatcher.Invoke 方法。但有些不对劲..

namespace Bizantyjskie
{
    public static class ControlExtensions
    {

        public static void InvokeIfRequired(this Control control, Action action)
        {
            if (System.Threading.Thread.CurrentThread != control.Dispatcher.Thread)
                control.Dispatcher.Invoke(action);
            else
                action();
        }
        public static void InvokeIfRequired<T>(this Control control, Action<T> action, T parameter)
        {
            if (System.Threading.Thread.CurrentThread != control.Dispatcher.Thread)
                control.Dispatcher.Invoke(action, parameter);
            else
                action(parameter);
        }
    }

    class watki
    {
        public watki(MainWindow mw)
        {
            _mw = mw;
        }
        public MainWindow _mw;

        public void dzialaj()
        {
            Thread watek1 = new Thread(new ThreadStart(w1));
            watek1.Start();
        }

        private void w1()
        {

            string godz = DateTime.Now.TimeOfDay.ToString();
            ControlExtensions.InvokeIfRequired((value) => _mw.tb_w1.Text = value, godz);
        }
      }
     }

问题出在

ControlExtensions.InvokeIfRequired((value) => _mw.tb_w1.Text = value, 神);

我遇到了一个错误。

无法将 lambda 表达式转换为类型 'System.Windows.Controls.Control' 因为它不是委托类型

【问题讨论】:

  • Lambda 语法错误,您想要更多类似于ControlExtensions.InvokeIfRequired(() =&gt; { _mw.tb_w1.Text = godz }); 的内容,尽管这取决于InvokeIfRequired 对方法签名的要求,您可以发布该方法的签名吗?你只是缺少括号吗?例如ControlExtensions.InvokeIfRequired((value) =&gt; { _mw.tb_w1.Text = value }, godz);

标签: c# wpf multithreading invoke


【解决方案1】:

您将扩展方法作为静态方法调用而忘记传递参数。改成这样:

_mw.InvokeIfRequired(value => _mw.tb_w1.Text = value, godz);

或者,如果您仍想将其作为静态方法调用:

ControlExtensions.InvokeIfRequired(_mw, 
    value => _mw.tb_w1.Text = value, godz);

【讨论】:

  • 好地方 :) 我自己也错过了,这是一个漫长的圣诞节,喝了很多酒
  • 不起作用。第一个 _mw 它是 MainWindow 类中的控件对象,所以我这个对象没有 InvokeIfRequired 方法。第二个,我得到一个错误Cannot implicitly convert type 'string' to 'Bizantyjskie.MainWindow'
  • @user1031034 我更新了我的答案,它有一个小错字。 InvokeIfRequired 是一种扩展方法,因此可以使用与派生自Control 的任何类的实例方法相同的语法来调用它。
【解决方案2】:

试试这个

private void w1()
{
    string godz = DateTime.Now.TimeOfDay.ToString();
    ControlExtensions.InvokeIfRequired((value) => { _mw.tb_w1.Text = value; }, godz);
}

我认为您的“值”成员是传递给委托的参数,但如果不查看 InvokeIfRequired 的签名我无法确定 - 如果它是 object,您不需要演员表吗?

例如

ControlExtensions.InvokeIfRequired((value) => { _mw.tb_w1.Text = (string)value; }, godz);

编辑:

抱歉没有看到上面的签名!看起来您只是缺少 InvokeIfRequired 的通用参数:

ControlExtensions.InvokeIfRequired<string>((value) => { _mw.tb_w1.Text = value; }, godz);

应该可以的:)

另一种方法是调用非泛型方法并在委托范围内捕获字符串变量:

ControlExtensions.InvokeIfRequired(() => { _mw.tb_w1.Text = godz; });

我觉得比较干净

【讨论】:

  • 签名在上面,我相信'public static void InvokeIfRequired(this Control control, Action action, T parameter)'
  • 啊,没看到 :D
  • 以上列出的解决方案都不能解决问题。
猜你喜欢
  • 1970-01-01
  • 2013-10-16
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多