调用线程无法访问此对象,因为在通过类的析构函数从画布中删除 Label 时,其他线程拥有它
本文关键字:线程 布中 删除 析构函数 Label 拥有 其他 访问 对象 因为 调用 | 更新日期: 2023-09-27 17:56:23
我有一个对象 IntervalLabel,当这个对象被删除时,当调用析构函数时,我无法从画布中删除标签,
这段代码对我来说很有意义,但它会导致错误
commonParameters.mainCanvas.Children.Remove(intervalLabel);
错误是:
An unhandled exception of type 'System.InvalidOperationException' occurred
in WindowsBase.dll
附加信息:
The calling thread cannot access this object because a different thread owns it.
此外,这行代码不会导致错误,
intervalLabel.MouseLeftButtonDown -= new
System.Windows.Input.MouseButtonEventHandler(IntervalLabel_MouseDown);
如何通过析构函数从画布中删除标签?
class IntervalLabel
{
private Label intervalLabel;
public IntervalLabel(Canvas mainCanvas)
{
intervalLabel = new Label();
mainCanvas.Children.Add(intervalLabel);
intervalLabel.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(IntervalLabel_MouseDown);
}
private void IntervalLabel_MouseDown(object sender, MouseEventArgs e)
{
//....
}
~IntervalLabel()
{
intervalLabel.MouseLeftButtonDown -= new System.Windows.Input.MouseButtonEventHandler(IntervalLabel_MouseDown);
commonParameters.mainCanvas.Children.Remove(intervalLabel);
}
}
终结
器(为您运行~ClassName()
函数的东西)在它自己的线程上运行,这就是您收到错误的原因,但是您无法执行正常的封送处理,因为当 finializer 调用您的函数时,窗口的上下文可能已经被销毁了。
你不应该把这样的操作放在终结器中,这些操作应该放在类的Dispose
函数中。
//Marking the class sealed so we don't need to deal with
// the "protected virtual void Dispose(bool disposing)" pattern.
sealed class IntervalLabel : IDisposable
{
private Label intervalLabel;
public IntervalLabel(Canvas mainCanvas)
{
intervalLabel = new Label();
mainCanvas.Children.Add(intervalLabel);
intervalLabel.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(IntervalLabel_MouseDown);
}
private void IntervalLabel_MouseDown(object sender, MouseEventArgs e)
{
//....
}
public void Dispose()
{
intervalLabel.MouseLeftButtonDown -= new System.Windows.Input.MouseButtonEventHandler(IntervalLabel_MouseDown);
commonParameters.mainCanvas.Children.Remove(intervalLabel);
}
}
然后,您需要确保在您使用的任何容器中处理完对象后将其处理掉。
话虽如此,你的设计看起来真的很奇怪。我希望从中衍生出一种叫做IntervalLabel
的东西,Label
里面不包含标签。此外,如果您所做的只是处理鼠标按下事件,则看起来这根本不需要一个类,并且可以在 XAML 或窗体的代码隐藏中处理。