我真的被困在这里......我有一个XAML页面UI,并希望每次用户与UI交互时都调用异步函数。
我使用SignalR进行联网:
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并向其传递回调?
答案 0 :(得分: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.
}
处理命令async(来自gui事件)时,不要忘记禁用控件以防止执行命令多于。
答案 1 :(得分:0)
不要使用async void
方法。如果您不需要返回值,请使用async Task
- 如果您这样做,请使用async Task<SomeType>
。
然后,当您需要调用异步方法时(按照惯例,这些方法应该命名为ConnectAsync
和SendTouchAsync
),await
它:
await SendTouchAsync(...);
当异步工作流程结束时,您的延续将被编组回UI线程(因为您在同步上下文中await
编辑),并且您可以轻松地操作UI。
await
时, async void
似乎有效,但问题是调用者无法跟踪异步工作流 - 就调用者而言,该方法刚刚结束当时和现在,调用者中的代码照常继续。
确保将Canvas_PointerPressed
标记为async
- 遗憾的是,在这种情况下,必须为async void
。确保永远不要直接调用事件处理程序 - UI线程可以正确处理回调,而代码则不能。如果您需要来自其他方法的相同逻辑,只需将其分离为适当的async Task
方法和await
来自事件处理程序的方法。