Winforms appel de méthode asynchrone raccroche programme
J'ai travaillé autour de ce problème pour un certain temps, mais maintenant j'aimerais vraiment comprendre ce qui va mal. J'ai une assez simple demande (c'est un turtoise SVN du plugin pour youtrack, mais je peux reproduire le problème avec un trivial application winforms).
J'ai une méthode asynchrone ResolveIssue
public async Task<bool> ResolveIssue(Issue issue, int revision, string[] pathList)
{
await Task.Delay(1000);
return true;
}
Tout ce que j'ai à faire pour créer un blocage est d'appeler cette méthode asynchrone dans un Button
gestionnaire d'événements, et d'appeler Task.Wait
ou Task.Result
, à l'instar de ce
private void buttonOk_Click(object sender, System.EventArgs e)
{
var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList);
if (asyncResolvedIssue.Result) {} //<== deadlock!
}
Maintenant je comprends que c'est plutôt bizarre d'avoir une méthode asynchrone et activement à l'attendre, mais pourquoi serait-il générer une impasse?!
- Pourquoi le 2 votes contre? Au moins partager un commentaire.
Vous devez vous connecter pour publier un commentaire.
Votre problème est que vous ne bloque le thread de l'INTERFACE utilisateur lorsque vous appelez
.Result
et vous dit à la poursuite aprèsTask.Delay
à exécuter sur le thread de l'INTERFACE utilisateur. Si vous êtes le blocage de l'INTERFACE utilisateur d'attente pour une tâche qui est bloqué sur l'attente de l'INTERFACE utilisateur de devenir libres, un classique de blocage.Deux solutions. Faites d'abord le bouton cliquez sur async trop.
Les gestionnaires d'événements sont le seul endroit où vous êtes autorisé à faire
async void
.L'autre option est de dire
Task.Delay
il n'a pas besoin d'avoir le reste de sa fonction exécuter sur le thread de l'INTERFACE utilisateur en définissantConfigureAwait(bool)
à false.Maintenant la ligne de code après la
Task.Delay
sera exécuté sur un pool de threads thread au lieu de le thread d'INTERFACE utilisateur et ne sera pas bloqué par le fait que le thread d'INTERFACE utilisateur est actuellement bloqué.