chiamare il metodo asincrono senza attendono #2

Ho un metodo asincrono:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

Io chiamo questo metodo come questo:

bool isValid = await ValidateRequestAsync("user1", "pass1");

Posso chiamare lo stesso metodo da un metodo sincrono, senza l’utilizzo di await parola chiave?

Ex:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

Penso che questo sarà causa di un deadlock.

MODIFICA

Di chiamare il metodo come sopra rende la chiamata non è mai fine. (Il metodo non raggiunge la fine più)

  • Credo che la chiamata di un metodo asincrono senza attendono sarà solo causare il metodo per essere chiamato in modo sincrono, il conseguente comportamento dipenderà da ciò che il vostro metodo effettivamente.
  • Ho provato! Sembra che la chiamata al metodo non finisce mai
  • il metodo è sempre chiamato in modo sincrono. Esso restituisce solo un compito, che è l’unica differenza. Tutta la magia è in attesa, non la chiamata.
  • Ah capisco, io in realtà non ho usato async ancora; ho bisogno di leggere di più sulla meccanica. Grazie.
  • È possibile che il tuo metodo di stallo, ma questo è un risultato da una logica non dal fatto che si sta chiamando in maniera sincrona.
  • Se si esegue questo codice su un singolo thread contesto di esecuzione, come ad esempio un thread dell’interfaccia utente, non sarà certamente un deadlock, perché il thread è in attesa che il thread diventi disponibile. Se si esegue su un threadpool thread, stai benissimo.
  • Ho modificato il tuo titolo. Si prega di vedere, “domande includono “tag” nei loro titoli?“, dove il consenso è “no, non dovrebbero”.
  • Farò la prossima volta, grazie

InformationsquelleAutor Catalin | 2013-11-05

 

2 Replies
  1. 64

    Se si chiama un metodo asincrono da un singolo thread contesto di esecuzione, come ad esempio un thread dell’interfaccia utente, e attendere il risultato in modo sincrono, c’è un’alta probabilità di deadlock. Nel tuo esempio, che la probabilità è del 100%

    Pensarci. Cosa succede quando si chiama

    ValidateRequestAsync(userName, password).Result

    Si chiama il metodo ValidateRequestAsync. Lì si chiama ReadAsStringAsync. Il risultato è che un’attività verrà restituito al thread dell’interfaccia utente, con una continuazione proseguirà in esecuzione sul thread UI, quando diventa disponibile. Ma, naturalmente, non diventerà mai disponibile, perché è in attesa (bloccato) per la fine dell’operazione. Ma il compito non può finire, perché è in attesa per il thread dell’interfaccia utente per diventare disponibili. Deadlock.

    Ci sono modi per evitare questa situazione di stallo, ma sono tutti una Cattiva Idea. Solo per completezza, di seguito potrebbe funzionare:

    Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

    Questa è una cattiva idea, perché si continuano a bloccare il thread dell’interfaccia utente di attesa e di non fare nulla di utile.

    Allora, qual è la soluzione? Andare in asincrono in tutto il modo. Il chiamante originale sul thread dell’interfaccia utente è molto probabilmente un gestore di eventi, in modo da assicurarsi che è asincrono.

    • Capito. La soluzione potrebbe essere creare una Sincronizzazione e un metodo Asincrono?
    • Alcuni asp.net web api azione di filtro non supporta i metodi Asincroni
    • Questo è vero, e .ConfigureAwait potrebbe aiutare. Ma attenzione: l’azione dei filtri deve correre veloce. Utilizzando .Result bloccare un thread, ed è qualcosa che dovrebbe essere evitato, in azione anche i filtri.
    • No, task.ConfigureAwait(false).Result di certo non il lavoro. Non compila, in quanto ConfigureAwait() non restituisce un Task.
    • Nel mio caso non mi interessa se si blocca il thread principale o non – è il processo che viene avviato manualmente una volta alla settimana – buona risposta
    • Perché sono Attività asincrone se avete di li attendono?
    • Alcune Api non offrono sync versioni dei loro compiti. Per esempio il UserManager in ASP.NET ha solo un GetUserAsync metodo. Penso che va benissimo utilizzare il Task.Run costruire per bloccare il filo, se si sta costruendo una API RESTful che non ha nessun thread dell’interfaccia utente in ogni caso, soprattutto perché la asp.net web API non sembrano essere progettati per async metodi di immissione, che non avrebbe alcun senso in ogni caso.

  2. 5

    si potrebbe utilizzare ritorno ValidateRequestAsync(userName, password).GetAwaiter().GetResult();

    • Oh, questo è davvero bello da guardare e merita di più upvotes.
    • Questo non sembra funzionare. Il processo si blocca, proprio come si farebbe ValidateRequestAsync(userName, password).Risultato. La “cattiva idea” di Kris’ risposta fa il trucco: Attività.Run(async () => attendono ValidateRequestAsync(userName, password)).Risultato

Lascia un commento