必须使用await / async在与DependencyObject相同的线程上创建DependencySource

时间:2019-01-07 14:22:54

标签: c# wpf multithreading

我正在ModelLoader中加载model3d,并使用async / await构造将其路径到TaskViewModel。

但是我有一个错误:“ System.ArgumentException:'必须在与DependencyObject相同的线程上创建DependencySource。”

我该如何解决。模型应加载到另一个线程上。

AsyncDelegateCommand-与任务配合使用

internal abstract class TaskViewModel : ViewModel
{
    private readonly AsyncDelegateCommand loadCommand;
    private readonly IModelLoader modelLoader;
    private Model3D model;

    public TaskViewModel(IModelLoader modelLoader)
    {
        this.modelLoader = modelLoader;
        loadCommand = new AsyncDelegateCommand(LoadAsync, () => CanLoad);
    }

    public ICommand LoadCommand => loadCommand;

    public bool CanLoad
    {
        get => canLoad;
        set => SetProperty(ref canLoad, value); // generate PropertyChanged
    }

    public Model3D Model
    {
        get => model;
        set => SetProperty(ref model, value);
    }

    private async Task LoadAsync()
    {
    string path = "somePath"
    Model3D model3D = await modelLoader.LoadAsync(path);
    Model = model3D;
    }
}

internal interface IModelLoader
{
    Task<Model3D> LoadAsync(string path);
}

internal sealed class ModelLoader : IModelLoader
{
    private readonly ModelImporter importer = new ModelImporter();
    private readonly Material material = new DiffuseMaterial(new SolidColorBrush(Colors.Beige));

    public ModelLoader()
    {
        importer.DefaultMaterial = material;
    }

    public Task<Model3D> LoadAsync(string path)
    {
        return Task.Factory.StartNew(() => Load(path), TaskCreationOptions.LongRunning);
    }

    private Model3D Load(string path)
    {
        return importer.Load(path);
    }
}

1 个答案:

答案 0 :(得分:0)

通常不能在一个线程上创建一个控件,然后再与另一个控件进行交互,但是冻结的可冻结对象可以在多个线程之间共享,因此您可以尝试在返回Model3D之前冻结它: / p>

private Model3D Load(string path)
{
    var model = importer.Load(path);
    model.Freeze();
    return model;
}

请参阅MSDN,了解有关可冻结物品的更多信息。