如何更新WPF MainWindow上的控件

时间:2013-08-16 13:59:52

标签: c# wpf multithreading

如何在下面的代码中更新我的label1文字?我得到一个“调用线程无法访问此对象,因为不同的线程拥有它”错误。我已经读过其他人使用过Dispatcher.BeginInvoke,但我不知道如何在我的代码中实现它。

public partial class MainWindow : Window
{
    System.Timers.Timer timer;

    [DllImport("user32.dll")]        
    public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);

    public struct tagLASTINPUTINFO
    {
        public uint cbSize;
        public Int32 dwTime;
    }

    public MainWindow()
    {
        InitializeComponent();
        StartTimer();
        //webb1.Navigate("http://yahoo.com");
    }

    private void StartTimer()
    {
        timer = new System.Timers.Timer();
        timer.Interval = 100;
        timer.Elapsed += timer_Elapsed;
        timer.Start();
    }

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
        Int32 IdleTime;
        LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
        LastInput.dwTime = 0;

        if (GetLastInputInfo(ref LastInput))
        {
            IdleTime = System.Environment.TickCount - LastInput.dwTime;
            string s = IdleTime.ToString();
            label1.Content = s;
        } 
    }
}

3 个答案:

答案 0 :(得分:6)

您可以尝试这样的事情:

if (GetLastInputInfo(ref LastInput))
{
    IdleTime = System.Environment.TickCount - LastInput.dwTime;
    string s = IdleTime.ToString();

    Dispatcher.BeginInvoke(new Action(() =>
    {
        label1.Content = s;
    }));
}

详细了解Dispatcher.BeginInvoke Method here

答案 1 :(得分:2)

您需要从主线程中保存Dispatcher.CurrentDispatcher

public partial class MainWindow : Window
{
    //...
    public static Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
    //...
}

然后,只要您需要在主线程的上下文中执行某些操作,就可以执行以下操作:

MainWindow.dispatcher.Invoke(() => {
   label1.Content = s;
});

注意,与Dispatcher.BeginInvoke不同,Dispatcher.Invoke是异步的。 您可能希望在此处进行同步调用。对于这种情况,异步调用似乎没问题,但通常你可能想要更新主要的thead上的UI,然后继续在当前线程上知道更新已经完成。

这是一个similar question的完整示例。

答案 2 :(得分:1)

有两种方法可以解决这个问题:

首先,您可以使用DispatcherTimer类而不是this MSDN article类,如{{3}}中所示,它会修改Dispatcher线程上Timer事件中的UI元素。< / p>

其次,使用现有的Elapsed类,您可以在timer_Elapsed事件中使用Timer方法代码,如下所示:

Dispatcher.BegineInvoke()
相关问题