2010-11-19 3 views
0

Язык: C# (МОФ)чтение данных из объекта, который заполняется из другого потока

Ситуация: Я должен загрузить 3D-сетки из файла, после чего я заселить Viewport3D.

Что я хочу сделать: я хочу загрузить 3D-сетку в BackgroundWorker, поэтому приложению не нужно останавливаться при загрузке 3D-сетки; это занимает несколько секунд.

Проблема: Проблема не в том, как использовать BackgroundWorker. Это хорошо документировано. Проблема возникает, когда я хочу заполнить Model3DGroup (3D-группу) Viewport3D.

При загрузке 3D-сетки из файла, в рабочем фоне, я заполняю пользовательский класс сетки всеми точками и треугольными индексами каждого объекта в сетке. Я храню их в Point3DCollections и Int32Collections соответственно.

public class LFSMeshObject 
{ 
    public Point3D Center; 
    public int Radius; 
    public int NumPoints; 
    public int NumTris; 

    public Color ObjectColor { get; private set; } 
    public Point3DCollection Points { get; private set; } 
    public Int32Collection Tris { get; private set; } 

Когда заселена объект передается обратно в GUI потоке, я могу читать все значения и свойства, хранящиеся в объекте просто отлично. Я также могу прочитать Point3Dcollections и Int32Collections, которые я копирую в MeshGeometry3D, которые входят в Model3DGroup, но затем получают исключение владельца потока, потому что свойства фонового заселенного объекта принадлежат фоновому потоку.

DiffuseMaterial mDMat; 
    MeshGeometry3D mGeom; 
    Debug.WriteLine("num objects in mesh : {0}", _trackMesh.NumObjects); 
    for (int a = 0; a < _trackMesh.NumObjects; a++) 
    { 
     mGeom = new MeshGeometry3D(); 
     mGeom.Positions = _trackMesh.TrackMeshObjects[a].Points; 
     mGeom.TriangleIndices = _trackMesh.TrackMeshObjects[a].Tris; 

     mDMat = new DiffuseMaterial(); 
     mDMat.Brush = new SolidColorBrush(_trackMesh.TrackMeshObjects[a].ObjectColor); 

     // thread owner exception 
     _mgTrack.Children.Add(new GeometryModel3D(mGeom, mDMat)); 
    } 

Является ли проблема, что я читаю объекты (Point3DCollection/Int32Collection) вместо простых значений, которые будут скопированы из фонового малонаселенных объекта?
Это так, что, когда вы обмениваетесь данными между потоками, вам нужно создать копии всех данных, которые вы хотите использовать (в другом объекте, т. Е. MeshGeometry/Modelgroup) в другом потоке? Можем ли мы не заполнять объект в фоновом режиме, а затем «просто использовать его» в другом потоке после завершения заполнения?

+0

Вышеуказанный метод не соответствует методу DoWork? –

+0

Бит кода с циклом, который устанавливает MeshGeometries, находится в потоке графического интерфейса. Порядок вещей, которые у меня есть сейчас, это: запустить фоновой рабочий, который инициализирует класс, который заполняет собой данные ячейки из файла. По завершении фоновой работник передает этот объект обратно в поток gui, который затем заполняет фактические MeshGeometry3D и GeometryModel3D. Это работает, если я НЕ использую объекты Point3DCollection и/или Int32Collection. Я должен использовать простые массивы Point3D [] и int []. Те, которые я могу передать непосредственно объектам MeshGeometry3D. – Victor

ответ

0

Простая и грязная вещь, чтобы попытаться передать указатель функции (обратный вызов делегата) в контекст потока, который вы запускаете из потока gui. Этот делегат, по сути, вернет то, что вы хотите прочитать, в тот момент, когда вы хотите прочитать его обратно в поток gui. Таким образом, обратный вызов создается в основном потоке. Это должно сработать.

+0

Макс, если элемент управления WPF связан с объектом, заполненным фоном, как это предотвратит попытку доступа потока пользовательского интерфейса к объекту, когда он будет обновляться рабочим потоком? Во многих приложениях поток пользовательского интерфейса должен быть бесплатным, чтобы обслуживать операции пользователя в сетке WPF или что-то еще ... У меня нет большого опыта работы с WPF, но я собираю много кода, сгенерированного XAML, который работает, и я не имеют доступа. – viejo

0

Тем временем я исправил проблему, используя простые массивы Point3D [] и int [] вместо xxxCollection. Затем, когда я заполняю 3D-модели этими массивами, он отлично работает. Ошибок владения нитями. Странно ... но, видимо, некоторые объекты (которые были созданы в фоновом потоке) могут быть просто недоступны в другом потоке, или я чего-то не хватает (возможно, я использовал только C# в течение 1,5 месяцев).

Смежные вопросы