Partager via


SYSK 348: InvokeRequired No More…

By now, we all have learned to call Control.InvokeRequired to avoid the following error when updating UI from another thread or calling other apartment threaded objects that expect to be called on a thread they were created on:

The calling thread cannot access this object because a different thread owns it.

In WPF though, the way to do same is as follows:

  1. Instead of calling Control.InvokeRequired, call Control.CheckAccess
  2. Use Control.Dispatcher.Invoke or BeginInvoke if CheckAccess returned false

 

Below is a simple example of doing just that:

 

using System;

using System.Windows;

namespace WPFWinApp

{

    public partial class Window1 : System.Windows.Window

    {

        public Window1()

        {

            InitializeComponent();

        }

        void StartThread(object source, EventArgs e)

        {

            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(DoWork));

        }

        void DoWork(object param)

      {

           

            try

            {

                if (base.CheckAccess() == true)

                    this.label1.Content = DateTime.Now.ToLongTimeString();

                else

                    base.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,

                        new System.Threading.WaitCallback(DoWork), param);

            }

            catch (Exception ex)

            {

                System.Windows.MessageBox.Show(ex.Message);

                System.Diagnostics.Debug.WriteLine(ex.Message);

            }

        }

    }

}

Comments

  • Anonymous
    May 11, 2007
    Maybe using System.Threading.SynchronizationContext is more elegant?

  • Anonymous
    May 14, 2007

  1. should be Instead of calling Control.InvokeRequired, call Control.Dispatcher.CheckAccess()