2

ユーザーが XAML に保存されているさまざまな 3Dmodels を表示し、TrackballDecorator を使用して Viewport3D を操作できるプログラムがあります。これらの XAML ファイルには、WPF 3D - カメラ ビューを保存して読み込むにはどうすればよいですか? という質問への回答の変更を使用して、TrackballDecorator に適用していた変換が含まれています

最近、プロジェクトを .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 の読み込みが完了していないため、null Transform が返されるため、これは機能しません。

私がやりたいことは次のとおりです。

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 キーワードを使用できません。この制限を克服または回避する方法はありますか?

4

3 に答える 3

2

ここには 2 つの問題があります。

一方では、EAP 操作を Task に変換する「標準的な」方法は、TaskCompletionSourceを使用して、ソースのTaskプロパティを返すことです。イベント ハンドラーはSetResultを呼び出して、Task が完了したことを通知し、その結果を設定します。

次のように書くことができます。

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 オブジェクトを返し、それにノードを非同期的に追加します。必要に応じて INotifyPropertyChanged を発生させるのは ViewPort3D 次第であり、これらの変更に反応するのは TrackballDecorator と Transforms 次第です。

TaskCompletionSource の使用は、2 番目の問題の回避策にすぎません。

于 2013-08-07T09:48:13.660 に答える
1

ここで見られるように、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-06T21:10:45.373 に答える