我有一个程序,用户可以在该程序中查看保存在XAML中的各种3D模型,然后使用一个Viewport3D操作TrackballDecorator。这些XAML文件中包含的转换是我使用问题TrackballDecorator的答案中的修改应用到WPF 3D -如何保存和加载相机视图?的转换。
最近,我将项目切换到.net 4.5框架,以利用XamlReader类的新异步功能,这与我访问模型保存的转换的方式发生了冲突。
我目前所做的是:
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还没有完成加载,因此返回了一个空转换。
我想做的是:
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关键字。有什么方法可以克服或克服这个限制吗?
发布于 2013-08-06 21:10:45
最后,我使用XamlReader LoadCompleted事件处理程序和SlimSemaphore解决了这个问题,如下所示:是否有可能等待一个事件而不是另一个异步方法?
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();
}发布于 2013-08-07 09:48:13
这里有两个问题。
一方面,将EAP操作转换为任务的“规范”方法是使用TaskCompletionSource并返回源的任务属性。事件处理程序调用SetResult以指示任务完成并设置其结果。
你可以这样写:
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只是第二个问题的解决办法。
发布于 2013-08-06 21:15:54
您应该能够创建一个任务并等待它
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) };
}https://stackoverflow.com/questions/18089183
复制相似问题