调用线程无法访问此对象,因为不同的线程拥有它 - WPF [重复]

Posted

技术标签:

【中文标题】调用线程无法访问此对象,因为不同的线程拥有它 - WPF [重复]【英文标题】:The Calling thread cannot access this object because a different thread owns it - WPF [duplicate] 【发布时间】:2014-02-13 22:05:39 【问题描述】:

我有通过套接字连接的硬件。

我必须每 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;
    

但是当我运行应用程序时,它会抛出错误:

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

我研究并了解了 Dispatcher.Invoke,但无法在我的代码中实现它。

【问题讨论】:

【参考方案1】:

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

if (client.Connected == true)

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

if (client.Connected == true)

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

如果您收到错误An object reference is required for the non-static field, method, or property,请使用此

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

【讨论】:

Duad Khan:上面的示例给了我一个错误:无法将 Lambda 表达式转换为“System.delegate”,因为它不是委托类型 检查我所做的编辑。有关此错误的更多信息:(***.com/questions/9549358/…) 完美男人 .. 非常感谢! :) :D【参考方案2】:

如果您出于某种原因不想使用 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);

【讨论】:

很棒的@Fayilt 你的代码对我来说很好:) :)【参考方案3】:

试试这个:

System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate

    // Update UI component here
    CheckBox.IsChecked = false;
);

【讨论】:

这有所帮助,而其他一切都失败了。 看不到它是如何工作的。上述代码中参数的顺序不正确。 @dotNET:在与Dispatcher关联的线程上以指定优先级同步执行指定线程。可能是您期待 Invoke 方法的另一个重载。上述代码中的参数顺序绝对正确,请参见 msdn:msdn.microsoft.com/en-us/library/ms591593(v=vs.110).aspx

以上是关于调用线程无法访问此对象,因为不同的线程拥有它 - WPF [重复]的主要内容,如果未能解决你的问题,请参考以下文章

调用线程无法访问此对象,因为不同的线程拥有它 - WPF [重复]

“调用线程无法访问此对象,因为不同的线程拥有它”从 WPF 中的不同线程更新 UI 控件时出现错误

调用线程无法访问此对象,因为另一个线程拥有它[重复]

wpf 调用线程无法访问此对象,因为另一个线程拥有该对象。

调用线程无法访问此对象 - Timer [重复]

Wpf中“由于其他线程拥有此对象,因此调用线程无法对其进行访问”