例外:应用程序调用了为不同线程编组的接口

private void LogInButton_Click(object sender, RoutedEventArgs e) { var api = new RestAPI("http://localhost:2624/", UsernameTextBox.Text, PasswordTextBox.Password); api.AutenticarUsuarioFinalizado += (o, args) => { ProgressBar.IsIndeterminate = false; ProgressBar.Visibility = Visibility.Collapsed; LogInButton.IsEnabled = true; if (args.Error) return; if (args.Resultado.Autenticado) { } }; api.AutenticarUsuario(); ProgressBar.Visibility = Visibility.Visible; ProgressBar.IsIndeterminate = true; LogInButton.IsEnabled = false; } 

api.AutenticarUsuario(); 异步调用rest API,完成后调用事件处理程序api.AutenticarUsuarioFinalizado并在行ProgressBar.IsIndeterminate = false中得到此错误; 因为调用打开一个新线程,我该如何解决? 错误是:

该应用程序调用了一个为不同线程编组的接口。

问题是您的事件处理程序不在UI线程上执行。 我认为解决这个问题的最佳方法是使用TaskCompletionSource将您的EAP(基于事件的异步模式)方法转换为TAP(基于任务的异步模式):

 public static Task AutenticarUsuarioAsync(this RestAPI api) { var tcs = new TaskCompletionSource(); api.AutenticarUsuarioFinalizado += (sender, args) => { if (args.Error) tcs.TrySetException(new SomeAppropriateException()); else tcs.TrySetResult(args.Resultado); }; api.AutenticarUsuario(); return tcs.Task; } … private async void LogInButton_Click(object sender, RoutedEventArgs e) { var api = new RestAPI( "http://localhost:2624/", UsernameTextBox.Text, PasswordTextBox.Password); ProgressBar.Visibility = Visibility.Visible; ProgressBar.IsIndeterminate = true; LogInButton.IsEnabled = false; try { var resultado = await api.AutenticarUsuarioAsync(); if (resultado.Autenticado) { // whatever } } catch (SomeAppropriateException ex) { // handle the exception here } finally { ProgressBar.IsIndeterminate = false; ProgressBar.Visibility = Visibility.Collapsed; LogInButton.IsEnabled = true; } } 

因为await Task将始终在原始上下文中恢复,所以您不会以这种方式获得exception。 作为一个额外的优势,您不必像使用EAP一样“内向外”编写代码。

您还应该考虑使用绑定,而不是手动设置UI控件的属性。

您的AutenticarUsuarioFinalizado事件处理程序可能正在与UI线程不同的线程中执行。 您应该只从UI线程修改/创建UI对象。 在事件处理程序中使用调度程序,请在此处查看: 在WinRT中的UI线程上运行代码

 var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher; api.AutenticarUsuarioFinalizado += (o, args) => { dispatcher.RunAsync(DispatcherPriority.Normal, () => ProgressBar.IsIndeterminate = false; ProgressBar.Visibility = Visibility.Collapsed; [...]