Utiliser async / attendre avec le répartiteur.BeginInvoke()

j'ai une méthode avec un code qui fait un await fonctionnement:

public async Task DoSomething()
{
    var x = await ...;
}

j'ai besoin de ce code pour fonctionner sur le fil du répartiteur. Maintenant,Dispatcher.BeginInvoke() est awaitable, mais je ne peux pas marquer le lambda async pour exécuter le await à partir de l'intérieur, comme ceci:

public async Task DoSomething()
{
    App.Current.Dispatcher.BeginInvoke(async () =>
        {
            var x = await ...;
        }
    );
}

À l'intérieur async, j'obtiens l'erreur:

ne peut pas convertir l'expression lambda en système de type'.Délégué ' parce que ce n'est pas un délégué type.

Comment puis-je travailler avec async de l'intérieur Dispatcher.BeginInvoke()?

21
demandé sur Gigi 2014-05-03 13:24:46

2 réponses

réponse peut avoir introduit un bug obscur. Ce code:

public async Task DoSomething()
{
    App.Current.Dispatcher.Invoke(async () =>
    {
        var x = await ...;
    });
}

utilise Dispatcher.Invoke(Action callback) outrepasser la forme de Dispatcher.Invoke, qui accepte un async void lambda dans ce cas particulier. Cela peut conduire à un comportement tout à fait inattendu, comme cela se produit habituellement avec async void méthode.

Vous êtes probablement à la recherche de quelque chose comme ceci:

public async Task<int> DoSomethingWithUIAsync()
{
    await Task.Delay(100);
    this.Title = "Hello!";
    return 42;
}

public async Task DoSomething()
{
    var x = await Application.Current.Dispatcher.Invoke<Task<int>>(
        DoSomethingWithUIAsync);
    Debug.Print(x.ToString()); // prints 42
}

Dans ce cas, Dispatch.Invoke<Task<int>> accepte un Func<Task<int>> argument et renvoie la correspondante Task<int> qui est awaitable. Si vous n'avez pas besoin renvoyer rien DoSomethingWithUIAsync, il suffit d'utiliser Task au lieu de Task<int>.

alternativement, utilisez un des Dispatcher.InvokeAsync méthodes.

43
répondu noseratio 2017-05-23 12:26:19

Utiliser Dispatcher.Invoke()

public async Task DoSomething()
{
    App.Current.Dispatcher.Invoke(async () =>
    {
        var x = await ...;
    });
}
-3
répondu Muhammad Umar 2014-05-03 09:59:49