108 votes

Impossible de convertir implicitement le type 'string' en 'System.Threading.Tasks.Task<string>'.

Je suis novice en matière de programmation asynchrone. Après avoir parcouru quelques exemples de codes asynchrones, j'ai pensé écrire un simple code asynchrone.

J'ai créé une application Winform simple et dans le formulaire j'ai écrit le code suivant. Mais cela ne fonctionne pas

private Task<string> methodAsync() {
    Thread.Sleep(10000);
    return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
}

private async void button1_Click(object sender, EventArgs e)
{
    string s = await methodAsync();
    MessageBox.Show(s);
}

Quelqu'un pourrait-il mettre un peu de lumière ici

167voto

Servy Points 93720

Le type de retour listé de la méthode est Task<string> . Vous essayez de retourner un string . Ils ne sont pas identiques, et il n'y a pas de conversion implicite de la chaîne de caractères en Task<string> d'où l'erreur.

Vous confondez probablement cela avec un async dans laquelle la valeur de retour est automatiquement enveloppée dans une balise Task par le compilateur. Actuellement, cette méthode n'est pas une méthode asynchrone. Vous avez très certainement voulu faire cela :

private async Task<string> methodAsync() 
{
    await Task.Delay(10000);
    return "Hello";
}

Il y a deux changements essentiels. Premièrement, la méthode est marquée comme async ce qui signifie que le type de retour est entouré d'une étiquette Task ce qui permet de compiler la méthode. Ensuite, nous ne voulons pas faire une attente bloquante. En règle générale, lorsque vous utilisez la méthode await évitez toujours les attentes bloquantes lorsque vous le pouvez. Task.Delay est une tâche qui sera achevée après le nombre de millisecondes spécifié. Par await -En exécutant cette tâche, nous effectuons effectivement une attente non bloquante pour ce moment (en réalité, le reste de la méthode est une continuation de cette tâche).

Si vous préférez une manière 4.0 de le faire, sans utiliser await vous pouvez le faire :

private Task<string> methodAsync() 
{
    return Task.Delay(10000)
        .ContinueWith(t => "Hello");
}

La première version se compilera en quelque chose qui ressemblera plus ou moins à ceci, mais elle contiendra un peu de code supplémentaire pour la gestion des erreurs et d'autres fonctionnalités de l'interface utilisateur. await nous n'avons pas d'effet de levier ici.

Si votre Thread.Sleep(10000) est destiné à servir de substitut à une méthode de longue durée, plutôt que de simple moyen d'attendre un moment, vous devrez vous assurer que le travail est effectué dans un autre thread, au lieu du contexte actuel. Le moyen le plus simple d'y parvenir est d'utiliser Task.Run :

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            SomeLongRunningMethod();
            return "Hello";
        });
}

Ou plus probablement :

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            return SomeLongRunningMethodThatReturnsAString();
        });
}

79voto

Jaswant Agarwal Points 982

Utiliser la méthode FromResult

public async Task<string> GetString()
{
   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");
}

30voto

user2388853 Points 1407

Au-delà de l'utilisation problématique de async comme l'a fait remarquer @Servy, l'autre problème est que vous devez explicitement obtenir T de Task<T> en appelant Task.Result. Notez que la propriété Resultat bloquera le code asynchrone, et doit être utilisée avec précaution.

Essayez :

private async void button1_Click(object sender, EventArgs e)
{
    var s = await methodAsync();
    MessageBox.Show(s.Result);
}

-2voto

Dans mon cas.

        string ip = _GetStoreIpaddress().Result;

    private async Task<string> _GetStoreIpaddress()
    {
        string _store_iP = "";
        var Ip_address = await App.SQLiteDb.GetItemsAsync();
        if (Ip_address != null)
        {
            _store_iP = Ip_address.ToString();
        }

        return _store_iP;
    }

-3voto

    //source    
    public async Task<string> methodName()
            {
             return Data;
             }

    //Consumption
     methodName().Result;

J'espère que cela vous aidera :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X