Sto chiamando un metodo di libreria asincrona con ConfigureAwait (false). Ma, finisco sempre con lo stallo. (Lo sto usando nell'API controller ASP.NET) Ma, se utilizzo lo stesso metodo incluso in Task.Run(), funziona perfettamente.Perché ConfigureAwait (false) non funziona mentre Task.Run() funziona?
La mia comprensione è, Se il metodo di libreria non utilizza ConfigureAwait internamente, l'aggiunta di ConfigureAwait non risolverà il problema poiché nella chiamata alla libreria si verificherà un deadlock (si bloccherà su di esso utilizzando .Result). Ma, se questo è il motivo per cui funziona in Task.Run() in quanto non riuscirà a continuare nello stesso contesto/thread.
Questo article ne parla. A proposito, ho preparato molti articoli di Stephen Cleary. Ma, perché Task.Run() funziona è un mistero.
Codice frammento:
// This Create Method results in Deadlock
public async Task<string> Create(MyConfig config)
{
Document doc = await Client.CreateDocumentAsync(CollectionUri, config).ConfigureAwait(false);
return doc.Id;
}
// Uses Task.Run() which works properly, why??
public string Create(MyConfig config)
{
Document doc = Task.Run(() => Client.CreateDocumentAsync(CollectionUri, config)).Result;
return doc.Id;
}
[HttpPost]
public ActionResult CreateConfig(MyConfig config)
{
string id = Create(config).Result;
return Json(id);
}
Non si dovrebbe utilizzare ConfigureAwait (false) per garantire la continuazione utilizzando ThreadPool? e sì, ho reso async il metodo CreateConfig. Ma, volevo capire meglio il concetto esattamente sul perché Task.Run() non crea alcun problema. –
@KrunalModi 'ConfigureAwait (false)' configura solo le continuazioni per utilizzare il threadpool, non l'invocazione di 'Client.CreateDocumentAsync' – Lukazoid
@KrunalModi non ha senso usare' ConfigureAwait' con una chiamata asincrona che internamente ha un'altra chiamata asincrona che * non * è usato con 'ConfigureAwait'. 'ConfigureAwait (false)' dovrebbe essere usato * quasi * ovunque, e specialmente nelle librerie. Solo le chiamate di livello superiore (quelle nel contesto di sincronizzazione dell'interfaccia utente) non hanno bisogno di 'ConfigureAwait (false)' perché la continuazione deve essere eseguita nel contesto di sincronizzazione dell'interfaccia utente. Per le librerie che non utilizzano 'ConfigureAwait (false)' internamente, usando 'attende Task.Run (() => ...)' o 'attende Task.Run (() => ...). ConfigureAwait (false) 'è una buona soluzione. –