Поток вызовов не может получить доступ к этому объекту, потому что ему принадлежит другой поток, WPF

У меня есть аппаратное обеспечение, которое подключено через сокет,

теперь мне нужно проверить, что аппаратное обеспечение подключено или нет, каждые 5 секунд, которое отображается с помощью флажка

i реализовала функцию:

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;
    }
}

Но когда я запускаю приложение, он бросает ошибку.

Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток.

Я исследовал и узнал о Dispatcher.Invoke, но не смог реализовать это в своем коде.

Ответ 1

Доступ к элементу ui можно получить только одним потоком пользовательского интерфейса. CheckBox Требуется поток пользовательского интерфейса, и ваш таймер работает в разных потоках. Простой код для использования диспетчера

if (client.Connected == true)
{
    Dispatcher.Invoke(()=>{
        CheckBox.IsChecked =true;
    });
}

ИЛИ

if (client.Connected == true)
{
    Dispatcher.Invoke(new Action(()=>{
        CheckBox.IsChecked =true;
    }));
}

если вы получили сообщение об ошибке An object reference is required for the non-static field, method, or property, используйте этот

 Application.Current.Dispatcher.Invoke(() =>
 {
     // Your Code Goes here
 });

Ответ 2

Если вы не хотите использовать Диспетчер по какой-либо причине, вы можете использовать SynchronizationContext. Нет большой разницы, но я чувствую себя менее виноватым при использовании SynchronizationContext, поскольку это не специальный класс WPF:

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);
}

Ответ 3

Попробуйте следующее:

System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate
{
    // Update UI component here
    CheckBox.IsChecked = false;
});