2016-07-11 17 views
0

本当にここにこだわっています...私はXAMLページUIを持っており、ユーザーがUIと対話するたびに非同期関数を呼び出す必要があります。
私はネットワーキングのためのSignalRを使用します。同期UIスレッドからのコールバックで非同期メソッドを呼び出す

public static class ProtocolClient 
{ 
    private static HubConnection hubConnection; 
    private static IHubProxy protocolHubProxy; 

    public static async void connect(string server) 
    { 
     hubConnection = new HubConnection(server); 
     protocolHubProxy = hubConnection.CreateHubProxy("ProtocolHub"); 
     protocolHubProxy.On<Body>("BodiesChanged", body => 
      //call a callback to return body 
     ); 
     await hubConnection.Start(); //wait for connection 
    } 

    public static async void sendTouch(Touch touch) 
    { 
     Body body = await protocolHubProxy.Invoke<Body>("GetBodyForTouch", touch); 
     //call a callback to return body 
    } 
} 

UI:

public sealed partial class MainPage : Page 
{ 
    [...] 
    private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e) 
    { 
     [...] 
     switch (ptrPt.PointerDevice.PointerDeviceType) 
     { 
      case Windows.Devices.Input.PointerDeviceType.Mouse: 
       if (ptrPt.Properties.IsLeftButtonPressed) 
       { 
        //call sendTouch 
       } 
       break; 
      default: 
       break; 
     } 
     [...] 
    } 
} 

私はUIを変更することができ、コールバックを必要としています。どうすればconnectとsendTouchをUIから呼び出してコールバックを渡すことができますか?

答えて

0

コールバックは必要ありません。 await hubConnection.Start();ステートメントの後にコードを追加するだけです。あなたの方法は「複数の方法でカット」され、待ってから「続ける」でしょう。 awaitはブロッキングステートメントのように機能しますが、guiはフリーズしません。

public static async void connect(string server) 
{ 
    hubConnection = new HubConnection(server); 
    protocolHubProxy = hubConnection.CreateHubProxy("ProtocolHub"); 
    protocolHubProxy.On<Body>("BodiesChanged", body => 
     //call a callback to return body 
    ); 
    await hubConnection.Start(); //wait for connection 

    // add code here. 
} 

コマンドを非同期(guiイベントから)処理するときは、複数のコマンドを実行しないように制御を無効にすることを忘れないでください。

+0

ありがとうございます。しかし、体オブジェクトをUIに渡すにはどうすればいいですか??これらの関数は異なるクラスにあります。 – pythonimus

+0

'SignalR'は扱っていませんが、メッセージが到着するたびに' body'が呼び出されたときに 'Start()'メソッドが返されていると仮定します。したがって、受信したメッセージをどこで扱うべきかについての誤解があります。 'on 'イベントから 'await hubConnection.Start()'の後にオブジェクトを '移動'する必要はありません。そこのメッセージを処理してください。 –

+0

あなたは正しいです。 BUTクラスProtocolClientはUI要素と何も関係がありません。 – pythonimus

0

async voidメソッドを使用しないでください。値を返す必要がない場合は、async Taskを使用してください。そうした場合は、async Task<SomeType>を使用してください。その後

、あなたは非同期メソッドを呼び出すために(および慣例により、これらはConnectAsyncSendTouchAsyncのように名前を付ける必要があります)必要がある、awaitそれは:非同期ワークフローが終了すると

await SendTouchAsync(...); 

、あなたの継続が整列化されます(あなたが同期コンテキスト内からawaitを編集したため)UIスレッドに戻って、UIを簡単に操作できます。

awaitasync voidを使用すると問題が発生しますが、問題は発信者が非同期ワークフローを追跡する方法がないことです。発信者に関する限り、メソッドは今すぐ終了しました。発信者のコードは通常通り続きます。悲しいことに、このような場合には、それはasync voidでなければなりません -

することはあまりにもCanvas_PointerPressedasyncようにマークを付けていることを確認してください。イベントハンドラを直接呼び出さないようにしてください。UIスレッドはコールバックを正しく処理でき、コードは処理できません。他のメソッドから同じロジックが必要な場合は、イベントハンドラから適切なasync Taskメソッドとawaitメソッドに分離してください。

+0

ありがとうございますが、私はまだ体のオブジェクトを取得する方法の手がかりを持っていません何とか呼び出し元クラスのMainPageに。 – pythonimus

+0

@pythonimus戻り値を使用するだけです。署名を '非同期タスク SendTouchAsync(...)'に変更し、内部で 'return body;'を実行してください。 'await SendTouchAsync(...);'に戻り値があります。 – Luaan

+0

ありがとう、私の質問は、[On function](https://msdn.microsoft.com/en-us/library/dn433683(v=11118).aspx)からUIへのbodyオブジェクトの取得方法でした。 'protocolHubProxy.On (" BodiesChanged "、body => // bodyを返すコールバックを呼び出す); このActionコールバックを作成し、それをconnect関数に渡してコールバックできるようにするUI要素を変更しますか? – pythonimus

関連する問題