例外:应用程序调用被编组为一个不同的线程的接口 [英] Exception: The application called an interface that was marshalled for a different thread
问题描述
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 的,并得到符合这个错误的进度.IsIndeterminate = FALSE; 的因为调用打开一个新的线程,我怎么能解决这个问题?错误的是:
api.AutenticarUsuario(); calls a rest API asynchronously, when it's done it calls the event handler api.AutenticarUsuarioFinalizado and got this error in line ProgressBar.IsIndeterminate = false; because the call open a new thread, how can I fix it? the error is:
应用程序调用被编组为不同的线程的接口。
推荐答案
的问题是,你的事件处理程序没有在UI线程上执行。我认为解决这个问题的最好办法是将您的EAP(基于事件的异步模式)方法转换为使用为TAP(基于任务的异步模式) TaskCompletionSource
:
The problem is that your event handler doesn't execute on the UI thread. I think the best way to fix that is to convert your EAP (Event-based Asynchronous Pattern) method to TAP (Task-based Asynchronous Pattern) using TaskCompletionSource
:
public static Task<Resultado> AutenticarUsuarioAsync(this RestAPI api)
{
var tcs = new TaskCompletionSource<Resultado>();
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;
}
}
由于等待
ING一个工作
将始终在原有范围内继续,你不会得到一个除了这个样子。作为一个额外的好处,你不用写你的code由内向外,就像你做EAP
Because await
ing a Task
will always resume on the original context, you're not going to get an exception this way. As an additional advantage, you don't have to write your code "inside-out", like you do with EAP.
您也应该考虑使用绑定,而非手动设置你的UI控件的属性。
You should also consider using bindings, instead of setting the properties of your UI controls manually.
这篇关于例外:应用程序调用被编组为一个不同的线程的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!