使用同步 UI 线程的回调调用异步方法
本文关键字:回调 调用 异步方法 线程 同步 UI | 更新日期: 2023-09-27 17:56:23
我真的被困在这里了...我有一个 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
}
}
用户界面:
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 的回调。如何在 UI 中调用 connect 和 sendTouch 并向他们传递回调?
你不需要回调。只需在 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 事件)时,不要忘记禁用控件以防止多次执行命令。
不要使用async void
方法。如果不需要返回值,请使用 async Task
- 如果返回,请使用 async Task<SomeType>
。
然后,当您需要调用异步方法时(按照惯例,这些方法应命名为 ConnectAsync
和 SendTouchAsync
),await
它:
await SendTouchAsync(...);
异步工作流结束时,您的延续将被封送回 UI 线程(因为您从同步上下文中await
ed),并且您可以轻松地操作 UI。
当您使用async void
时,await
似乎有效,但问题是调用方无法跟踪异步工作流 - 就调用方而言,该方法当时和现在刚刚结束,调用方中的代码照常继续。
确保Canvas_PointerPressed
也标记为async
- 可悲的是,在这种情况下,它必须是 async void
.确保永远不要直接调用事件处理程序 - UI 线程可以正确处理回调,而代码不能。如果需要与其他方法相同的逻辑,只需将其分离为适当的async Task
方法,并将其与事件处理程序await
即可。