调用线程不能访问这个对象-不是一个UI对象



EDIT我删除了我的代码,因为它是不完整的和令人困惑的,但添加了一个最小的可重复的例子。为了澄清我的问题,下面所有的文字都经过了轻微的重写,添加了评论中的信息,但没有添加任何我在提问时不知道的东西,以便让评论与未来的读者保持相关性。我还更改了标题

试图在后台执行一些计算

在尝试之前,我确保我的Simulator类工作正常。我的计算是通过调用模拟器中的类方法启动的。当我尝试执行计算(无论是使用await, TaskFactory或其他此类工具)时,我无法访问MeshGeometry3D类成员调用线程不能访问这个对象,因为另一个线程拥有它"。

我可以通过向任务传递参数来克服这个困难,但是数据量相当大,所以如果可行的话,我更愿意在现有的对象上工作。

我读过这个,这个,这个,这个,这个和这个但是这些答案都假设一个UI元素,事实并非如此:我的MeshGeometry3D成员没有在UI中使用,在背景计算之前,期间或之后。

我读到这是人们开始时的一个常见问题,并且我应该在尝试访问属于主线程的数据时调用分派器,但我无法从我的模拟器类访问分派器(附带问题,是否有方法访问创建元素的分派器?)

所以我试图理解发生了什么,以便决定处理问题的最佳方法。从我读到目前为止,我看到两个选项:

  • 使用调度程序访问对象
  • 每次执行计算时创建罪魁祸首MeshGeometry3D

最小可复制示例

MainWindow.xaml.cs

using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Media3D;
namespace DispatcherObject
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Simulator Simulator;
public MainWindow()
{
InitializeComponent();
Simulator = new Simulator();
}                  
private void CreateMesh_Click(object sender, RoutedEventArgs e)
{
Simulator.mesh = new MeshGeometry3D();
}
private void AccessMesh_Click(object sender, RoutedEventArgs e)
{
CallSimulatorMethod();
}  
private async void CallSimulatorMethod()
{
await Task.Run(() =>Simulator.AccessMesh());
}
}
}

Simulator.cs

using System.Windows.Media.Media3D;
namespace DispatcherObject
{
class Simulator
{
public MeshGeometry3D mesh;
public void AccessMesh()
{
var foo = mesh.Normals;
}
}
}

使用前面的代码,如果您首先单击AccessMesh按钮,您将获得一个System。当然是NullReferenceException

如果你先点击CreateMesh,你会得到这个异常:

系统。InvalidOperationException HResult=0x80131509 Message=调用线程无法访问该对象,因为它属于不同的线程。Source=WindowsBase StackTrace: atSystem.Windows.Threading.Dispatcher.VerifyAccess ()System.Windows.DependencyObject。GetValue(DependencyProperty dp)System.Windows.Media.Media3D.MeshGeometry3D.get_Normals ()DispatcherObject.Simulator.AccessMesh ()C:Usersgeraudsourcerepos DispatcherObject DispatcherObject Simulator.cs:行11 .在DispatcherObject.MainWindow.b__4_0()中C:Usersgeraudsourcerepos DispatcherObject DispatcherObject MainWindow.xaml.cs:行33 . at . System.Threading.Tasks.Task.InnerInvoke(System.Threading.Tasks.Task.Execute ()

这个异常最初是在这个调用栈上抛出的:(外部代码)模拟器.cs中的dispatcherobject .模拟器. accessmesh (DispatcherObject.MainWindow.CallSimulatorMethod.AnonymousMethod__4_0 ()在MainWindow.xaml.cs(外部代码)

感谢所有帮助我找到答案的评论者,尤其是@Knoop。

我试图访问一个MeshGeometry3D,从DispatcherObject继承,从一个不同的线程,它是创建在。我通过在工作线程中重新创建对象来摆脱异常:

只有创建Dispatcher的线程可以访问直接DispatcherObject。

我想强调的事实是,这不是一个UI问题:虽然这个异常没有指定任何关于UI的东西,但它似乎主要遇到UI对象,正如Stack Overflow中对我和所有其他相关问题的评论所清楚显示的那样。

最新更新