首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可以等待XamlReader.LoadAsync()吗?

可以等待XamlReader.LoadAsync()吗?
EN

Stack Overflow用户
提问于 2013-08-06 19:50:01
回答 3查看 863关注 0票数 2

我有一个程序,用户可以在该程序中查看保存在XAML中的各种3D模型,然后使用一个Viewport3D操作TrackballDecorator。这些XAML文件中包含的转换是我使用问题TrackballDecorator的答案中的修改应用到WPF 3D -如何保存和加载相机视图?的转换。

最近,我将项目切换到.net 4.5框架,以利用XamlReader类的新异步功能,这与我访问模型保存的转换的方式发生了冲突。

我目前所做的是:

代码语言:javascript
复制
private Task<TrackballDecorator> loadModel(string path)
{
    var tempVP = new XamlReader().LoadAsync(XmlReader.Create(path)) as Viewport3D;
    return new TrackballDecorator() { Content = tempVP, Transform = (tempVP.Camera.Transform as Transform3DGroup) };
}

这不起作用,因为XamlReader还没有完成加载,因此返回了一个空转换。

我想做的是:

代码语言:javascript
复制
private async Task<TrackballDecorator> loadModelAsync(string path)
{
    var tempVP = await new XamlReader().LoadAsync(XmlReader.Create(path)) as Viewport3D;
    return new TrackballDecorator() { Content = tempVP, Transform = (tempVP.Camera.Transform as Transform3DGroup) };
}

但是,由于LoadAsync方法返回一个object而不是一个Task<object>,所以我不能使用await关键字。有什么方法可以克服或克服这个限制吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-06 21:10:45

最后,我使用XamlReader LoadCompleted事件处理程序和SlimSemaphore解决了这个问题,如下所示:是否有可能等待一个事件而不是另一个异步方法?

代码语言:javascript
复制
private SemaphoreSlim signal = new SemaphoreSlim(0, 1);

private async Task<TrackballDecorator> loadModel(string path) {
    XamlReader xr = new XamlReader();
    xr.LoadCompleted += new AsyncCompletedEventHandler(AsyncXamlComplete);
    var tempVP = xr.LoadAsync(XmlReader.Create(path)) as Viewport3D;

    await signal.WaitAsync();

    return new TrackballDecorator() { Content = tempVP, Transform = tempVP.Camera.Transform as Transform3DGroup) };
}

private void AsyncXamlComplete(Object sender, AsyncCompletedEventArgs e) {
    signal.Release();
}
票数 1
EN

Stack Overflow用户

发布于 2013-08-07 09:48:13

这里有两个问题。

一方面,将EAP操作转换为任务的“规范”方法是使用TaskCompletionSource并返回源的任务属性。事件处理程序调用SetResult以指示任务完成并设置其结果。

你可以这样写:

代码语言:javascript
复制
public Task<ViewPort3D> LoadViewPortAsync(string path)
{
     var tcs=new TaskCompletionSource();
     var reader=XmlReader.Create(path);
     ViewPort3D port=null;
     var  xr = new XamlReader();
     xr.LoadCompleted += (o,e)=>{
         tcs.SetResult(port);
         reader.Dispose();
     };
     port=xr.LoadAsync(reader);

     return tcs.Task;
}

一旦获得ViewPort3D对象,就可以创建转换

另一方面,“规范”的WPF方法是观察变化的对象并对其变化作出反应。LoadAsync返回根XAML对象并异步向其添加节点。应该由ViewPort3D适当地提高INotifyPropertyChanged,并由TrackballDecorator和转换来对这些更改作出反应。

使用TaskCompletionSource只是第二个问题的解决办法。

票数 2
EN

Stack Overflow用户

发布于 2013-08-06 21:15:54

您应该能够创建一个任务并等待它

代码语言:javascript
复制
private async Task<TrackballDecorator> loadModelAsync(string path)
{
    var tempVP = await Task.Factory.StartNew<Viewport3D>(() => (Viewport3D)XamlReader.Load(XmlReader.Create(path)));
    return new TrackballDecorator() { Content = tempVP, Transform = (tempVP.Camera.Transform as Transform3DGroup) };
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18089183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档