C# 调用线程无法访问此对象,因为另一个线程拥有它,即WPF

C# 调用线程无法访问此对象,因为另一个线程拥有它,即WPF,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个通过插座连接的硬件 现在我必须每隔5秒检查一次硬件是否已连接,并通过复选框显示 我实现了一个功能: private static System.Timers.Timer aTimer; public MainWindow() { InitializeComponent(); client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); aTimer = new System.T

我有一个通过插座连接的硬件

现在我必须每隔5秒检查一次硬件是否已连接,并通过复选框显示

我实现了一个功能:

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,但无法在代码中实现它。

尝试以下方法:

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

ui元素只能由一个ui线程访问。复选框需要UI线程,并且计时器在不同的线程上运行。使用Dispatcher的简单代码

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

如果收到错误
非静态字段、方法或属性需要对象引用,请使用此

 Application.Current.Dispatcher.Invoke(() =>
 {
     // Code causing the exception or requires UI thread access
 });

如果出于某种原因不想使用Dispatcher,可以使用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);
}
private static System.Timers.Timer aTimer;
私有同步上下文_uiContext=SynchronizationContext.Current;
公共主窗口()
{
初始化组件();
BeginConnect(remoteEP,新的异步回调(ConnectCallback),client);
aTimer=新的System.Timers.Timer();
aTimer.AutoReset=true;
aTimer.Appead+=新的ElapsedEventHandler(OnTimedEvent);
a时间间隔=2000;
aTimer.Enabled=true;
}
私有void OnTimedEvent(对象源,ElapsedEventArgs e)
{
_uiContext.Post(新的SendOrPostCallback(新操作)(o=>{
if(client.Connected==true)
{
控制台。写入线(“未连接”);
CheckBox.IsChecked=false;
}
其他的
{
控制台。写入线(“连接”);
CheckBox.IsChecked=false;
}
})),空);
}

Duad Khan:上面的示例给了我一个错误:无法将Lambda表达式转换为“System.delegate”,因为它不是我所做编辑的委托类型检查。有关此错误的详细信息:()完美男人。。非常感谢!!:):DGreat@Fayilt您的代码对我来说很好:):)这有帮助,而其他一切都失败了。看不出它是如何工作的。上述代码中的参数顺序不正确。@dotNET:它在与调度程序关联的线程上以指定的优先级同步执行指定的线程。可能您正期待调用方法的另一个重载。上述代码中的参数顺序完全正确,请参见msdn:
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);
}