Ich aktualisiere gerade eine Bibliothek mit einer API-Oberfläche, die in .NET 3.5 erstellt wurde. Daher sind alle Methoden synchron. Ich kann die API nicht ändern (d. H. Rückgabewerte in Task umwandeln), da dies eine Änderung aller Aufrufer erfordern würde. Somit bleibt mir nichts anderes übrig, als asynchrone Methoden synchron aufzurufen. Dies ist im Zusammenhang mit ASP.NET 4, ASP.NET Core und .NET/.NET Core-Konsolenanwendungen.Asynchrone Methoden aus nicht asynchronem Code aufrufen
Ich war vielleicht nicht klar genug - die Situation ist, dass ich bestehenden Code habe, der nicht async bewusst ist, und ich möchte neue Bibliotheken wie System.Net.Http und das AWS SDK verwenden, die nur asynchrone Methoden unterstützen. Also muss ich die Lücke überbrücken und in der Lage sein, Code zu haben, der synchron aufgerufen werden kann, aber dann anderswo asynchrone Methoden aufrufen kann.
Ich habe viel gelesen, und es gibt eine Reihe von Malen, die gefragt und beantwortet wurden.
Calling async method from non async method
Synchronously waiting for an async operation, and why does Wait() freeze the program here
Calling an async method from a synchronous method
How would I run an async Task<T> method synchronously?
Calling async method synchronously
How to call asynchronous method from synchronous method in C#?
Das Problem ist, dass die meisten Antworten unterschiedlich sind! Der häufigste Ansatz, den ich gesehen habe, ist die Verwendung .Result, aber das kann Deadlocks sein. Ich habe alles Folgende versucht, und sie funktionieren, aber ich bin nicht sicher, welcher der beste Ansatz ist, um Deadlocks zu vermeiden, eine gute Leistung zu haben und schön mit der Laufzeit zu spielen (in Bezug auf die Einhaltung von Task Schedulern, Task Creation Optionen, etc). Gibt es eine definitive Antwort? Was ist der beste Ansatz? wie man am besten Aufruf asynchroner Methoden in einer synchronen Weise
private static T taskSyncRunner<T>(Func<Task<T>> task)
{
T result;
// approach 1
result = Task.Run(async() => await task()).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 2
result = Task.Run(task).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 3
result = task().ConfigureAwait(false).GetAwaiter().GetResult();
// approach 4
result = Task.Run(task).Result;
// approach 5
result = Task.Run(task).GetAwaiter().GetResult();
// approach 6
var t = task();
t.RunSynchronously();
result = t.Result;
// approach 7
var t1 = task();
Task.WaitAll(t1);
result = t1.Result;
// approach 8?
return result;
}
Die Antwort ist, tun Sie es nicht. Sie fügen neue asynchrone Methoden hinzu und behalten die alten synchronen für die älteren Aufrufer bei. –
Das scheint ein bisschen hart und tötet wirklich die Fähigkeit, neuen Code zu verwenden. Zum Beispiel hat die neue Version des AWS SDK keine Nicht-Async-Methoden. Gleiches gilt für eine Reihe anderer Bibliotheken von Drittanbietern. Also, wenn du die Welt nicht umschreibst, kannst du keine davon benutzen? –
Option 8: Vielleicht könnte die [TaskCompletionSource] (https://msdn.microsoft.com/en-us/library/dd449174 (v = vs.110) .aspx) eine Option sein? – OrdinaryOrange