19

I have hardware which is connected through socket.

I have to check whether the hardware is connected or not every 5 seconds, which is indicated by a checkbox.

I have implemented a function:

private static System.Timers.Timer aTimer;
public MainWindow()
{
    InitializeComponent();
    client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
    aTimer = new System.Timers.Timer();
    aTimer.AutoReset = true;
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    aTimer.Interval = 2000;
    aTimer.Enabled = true;
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    if (client.Connected == true)
    {
        Console.WriteLine("Not Connected");
        CheckBox.IsChecked = false;
    }
    else
    {
        Console.WriteLine("Connected");
        CheckBox.IsChecked = false;
    }
}

But when I am running the application it is throwing error:

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

I researched and learned about Dispatcher.Invoke, but not been able to implement that in my code.

ouflak
  • 2,458
  • 10
  • 44
  • 49
Vivek Saurav
  • 2,235
  • 4
  • 25
  • 46

3 Answers3

35

A ui elememt can only be accessed by one UI Thread. CheckBox Requires UI Thread and your timer runs on different thread. Simple code to use Dispatcher

if (client.Connected == true)
{
    Dispatcher.Invoke(()=> {
        // Code causing the exception or requires UI thread access
        CheckBox.IsChecked =true;
    });
}

OR

if (client.Connected == true)
{
    Dispatcher.Invoke(new Action(()=> {
        // Code causing the exception or requires UI thread access
        CheckBox.IsChecked =true;
    }));
}

if you receive error An object reference is required for the non-static field, method, or property then use this

 Application.Current.Dispatcher.Invoke(() =>
 {
     // Code causing the exception or requires UI thread access
 });
Mujahid Daud Khan
  • 1,983
  • 1
  • 14
  • 23
  • Duad Khan : The above sample is giving me a error : Cannot convert Lambda expression to 'System.delegate' because it is not a delegate type – Vivek Saurav Jan 23 '14 at 11:39
  • 1
    Check for Edit i made. For More info about this Error: (http://stackoverflow.com/questions/9549358/cannot-convert-lambda-expression-to-type-system-delegate) – Mujahid Daud Khan Jan 23 '14 at 11:43
5

In case you don't want to use Dispatcher for some reason, you could use SynchronizationContext. There is not much difference, but I feel less guilty when using SynchronizationContext as it's not a WPF specific class:

private static System.Timers.Timer aTimer;
private SynchronizationContext _uiContext = SynchronizationContext.Current;

public MainWindow()
{
    InitializeComponent();

    client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
    aTimer = new System.Timers.Timer();
    aTimer.AutoReset = true;
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    aTimer.Interval = 2000;
    aTimer.Enabled = true;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{

    _uiContext.Post(new SendOrPostCallback(new Action<object>(o => {
        if (client.Connected == true)
        {
            Console.WriteLine("Not Connected");
            CheckBox.IsChecked = false;
        }
        else
        {
            Console.WriteLine("Connected");
            CheckBox.IsChecked = false;
        }
    })), null);
}
Fayilt
  • 1,042
  • 7
  • 16
4

Try this:

System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate
{
    // Update UI component here
    CheckBox.IsChecked = false;
});
Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
Ramashankar
  • 1,598
  • 10
  • 14
  • 1
    This helped whereas everything else failed. – IneedHelp Aug 12 '15 at 06:33
  • Can't see how it worked. The order of parameters is incorrect in the above code. – dotNET Oct 21 '15 at 03:54
  • @dotNET: It executes the specified thread synchronously at the specified priority on the thread on which the Dispatcher is associated with. May be you are expecting another overload of Invoke method. Order of the parameter is absolutely correct in the above code see at msdn : https://msdn.microsoft.com/en-us/library/ms591593(v=vs.110).aspx – Ramashankar Oct 22 '15 at 17:26