调用线程无法访问此对象,因为不同的线程拥有它 - 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 [重复]