Come dovrei eseguire un task asincrono metodo in modo sincrono?

Sto imparando async / await, e mi sono imbattuto in una situazione in cui ho bisogno di chiamare un metodo asincrono in modo sincrono. Come lo posso fare?

Metodo asincrono:

public async Task GetCustomers() { return await Service.GetCustomersAsync(); } 

Utilizzo normale:

 public async void GetCustomers() { customerList = await GetCustomers(); } 

Ho provato a utilizzare il seguente:

 Task task = GetCustomers(); task.Wait() Task task = GetCustomers(); task.RunSynchronously(); Task task = GetCustomers(); while(task.Status != TaskStatus.RanToCompletion) 

Ho anche provato un suggerimento da qui , tuttavia non funziona quando il dispatcher è in uno stato sospeso.

 public static void WaitWithPumping(this Task task) { if (task == null) throw new ArgumentNullException(“task”); var nestedFrame = new DispatcherFrame(); task.ContinueWith(_ => nestedFrame.Continue = false); Dispatcher.PushFrame(nestedFrame); task.Wait(); } 

Ecco l’eccezione e lo stack trace dalla chiamata RunSynchronously :

System.InvalidOperationException

Messaggio : RunSynchronously potrebbe non essere chiamato su un’attività non associata a un delegato.

InnerException : null

Fonte : mscorlib

StackTrace :

  at System.Threading.Tasks.Task.InternalRunSynchronously(TaskScheduler scheduler) at System.Threading.Tasks.Task.RunSynchronously() at MyApplication.CustomControls.Controls.MyCustomControl.CreateAvailablePanelList() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 638 at MyApplication.CustomControls.Controls.MyCustomControl.get_AvailablePanels() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 233 at MyApplication.CustomControls.Controls.MyCustomControl.b__36(DesktopPanel panel) in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 597 at System.Collections.Generic.List`1.ForEach(Action`1 action) at MyApplication.CustomControls.Controls.MyCustomControl.d__3b.MoveNext() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 625 at System.Runtime.CompilerServices.TaskAwaiter.c__DisplayClass7.b__1(Object state) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.Run() at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at MyApplication.App.Main() in C:\Documents and Settings\...\MyApplication\obj\Debug\App.g.cs:line 50 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() 

Ecco una soluzione che ho trovato che funziona per tutti i casi (compresi i dispatcher sospesi). Non è il mio codice e sto ancora lavorando per capirlo appieno, ma funziona.

Può essere chiamato usando:

customerList = AsyncHelpers.RunSync>(() => GetCustomers());

Il codice è di qui

 public static class AsyncHelpers { ///  /// Execute's an async Task method which has a void return value synchronously ///  /// Task method to execute public static void RunSync(Func task) { var oldContext = SynchronizationContext.Current; var synch = new ExclusiveSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(synch); synch.Post(async _ => { try { await task(); } catch (Exception e) { synch.InnerException = e; throw; } finally { synch.EndMessageLoop(); } }, null); synch.BeginMessageLoop(); SynchronizationContext.SetSynchronizationContext(oldContext); } ///  /// Execute's an async Task method which has a T return type synchronously ///  /// Return Type /// Task method to execute ///  public static T RunSync(Func> task) { var oldContext = SynchronizationContext.Current; var synch = new ExclusiveSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(synch); T ret = default(T); synch.Post(async _ => { try { ret = await task(); } catch (Exception e) { synch.InnerException = e; throw; } finally { synch.EndMessageLoop(); } }, null); synch.BeginMessageLoop(); SynchronizationContext.SetSynchronizationContext(oldContext); return ret; } private class ExclusiveSynchronizationContext : SynchronizationContext { private bool done; public Exception InnerException { get; set; } readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); readonly Queue> items = new Queue>(); public override void Send(SendOrPostCallback d, object state) { throw new NotSupportedException("We cannot send to our same thread"); } public override void Post(SendOrPostCallback d, object state) { lock (items) { items.Enqueue(Tuple.Create(d, state)); } workItemsWaiting.Set(); } public void EndMessageLoop() { Post(_ => done = true, null); } public void BeginMessageLoop() { while (!done) { Tuple task = null; lock (items) { if (items.Count > 0) { task = items.Dequeue(); } } if (task != null) { task.Item1(task.Item2); if (InnerException != null) // the method threw an exeption { throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException); } } else { workItemsWaiting.WaitOne(); } } } public override SynchronizationContext CreateCopy() { return this; } } } 

Sappi che questa risposta ha tre anni. L’ho scritto basandomi principalmente su un’esperienza con .Net 4.0, e molto poco con 4.5 specialmente con async-await . In generale è una soluzione semplice, ma a volte rompe le cose. Si prega di leggere la discussione nei commenti.

.Net 4.5

Basta usare questo:

 // For Task: will block until the task is completed... var result = task.Result; // For Task (not Task): will block until the task is completed... task2.RunSynchronously(); 

Vedi: TaskAwaiter , Task.Result , Task.RunSynchronously


.Net 4.0

Usa questo:

 var x = (IAsyncResult)task; task.Start(); x.AsyncWaitHandle.WaitOne(); 

…o questo:

 task.Start(); task.Wait(); 

Sorpreso nessuno ha menzionato questo:

 public Task BlahAsync() { // ... } int result = BlahAsync().GetAwaiter().GetResult(); 

Non è bello come alcuni degli altri metodi qui, ma ha i seguenti vantaggi:

  • non ingoiare le eccezioni (come Wait )
  • non tratterà alcuna eccezione generata in una AggregateException (come Result )
  • funziona sia per Task che per Task ( provalo tu stesso! )

Inoltre, dal momento che GetAwaiter è digitato anatra, questo dovrebbe funzionare per qualsiasi object restituito da un metodo asincrono (come ConfiguredAwaitable o YieldAwaitable ), non solo Task.


modifica: si noti che è ansible che questo approccio (o utilizzo di .Result ) si blocchi, a meno che non si .ConfigureAwait(false) aggiungere .ConfigureAwait(false) ogni volta che si attende, per tutti i metodi asincroni che possono essere raggiunti da BlahAsync() (non solo quelli che chiama direttamente). Spiegazione

 // In BlahAsync() body await FooAsync(); // BAD! await FooAsync().ConfigureAwait(false); // Good... but make sure FooAsync() and // all its descendants use ConfigureAwait(false) // too. Then you can be sure that // BlahAsync().GetAwaiter().GetResult() // won't deadlock. 

Se sei troppo pigro per aggiungere .ConfigureAwait(false) ovunque, e non ti importa delle prestazioni puoi in alternativa fare

 Task.Run(() => BlahAsync()).GetAwaiter().GetResult() 

È molto più semplice eseguire l’attività nel pool di thread, piuttosto che cercare di ingannare lo scheduler per eseguirlo in modo sincrono. In questo modo puoi essere certo che non si bloccherà. Le prestazioni sono influenzate dall’interruttore di contesto.

 Task DoSomethingAsync() { ... } // Starts the asynchronous task on a thread-pool thread. // Returns a proxy to the original task. Task task = Task.Run(() => DoSomethingAsync()); // Will block until the task is completed... MyResult result = task.Result; 

Sto imparando async / await, e mi sono imbattuto in una situazione in cui ho bisogno di chiamare un metodo asincrono in modo sincrono. Come lo posso fare?

La risposta migliore è che non lo fai , con i dettagli che dipendono da cosa è la “situazione”.

È un getter / setter di proprietà? Nella maggior parte dei casi, è meglio avere metodi asincroni che “proprietà asincrone”. (Per maggiori informazioni, vedi il mio post sul blog sulle proprietà asincrone ).

Si tratta di un’app MVVM e si desidera eseguire l’associazione asincrona dei dati? Quindi utilizzare qualcosa come il mio NotifyTask , come descritto nel mio articolo MSDN sull’associazione dati asincrona .

È un costruttore? Quindi probabilmente vorrai considerare un metodo factory asincrono. (Per maggiori informazioni, vedi il mio post sul blog sui costruttori asincroni ).

C’è quasi sempre una risposta migliore rispetto a sync-over-async.

Se non è ansible per la tua situazione (e lo sai ponendo una domanda qui descrivendo la situazione ), allora ti consiglio di usare solo il codice sincrono. Async fino in fondo è la cosa migliore; la sincronizzazione completa è la seconda migliore. Sync-over-async non è raccomandato.

Tuttavia, ci sono una serie di situazioni in cui è necessario sincronizzare-asincrono. Nello specifico, sei vincolato dal codice chiamante in modo che devi essere sincronizzato (e non avere assolutamente modo di ripensare o ribuild il tuo codice per consentire l’asincronia), e devi chiamare il codice asincrono. Questa è una situazione molto rara, ma di tanto in tanto si presenta.

In tal caso, è necessario utilizzare uno degli hack descritti nel mio articolo sullo sviluppo async brownfield , in particolare:

  • Blocco (ad esempio, GetAwaiter().GetResult() ). Si noti che questo può causare deadlock (come descrivo sul mio blog).
  • Esecuzione del codice su un thread del pool di thread (ad esempio Task.Run(..).GetAwaiter().GetResult() ). Si noti che ciò funzionerà solo se il codice asincrono può essere eseguito su un thread pool di thread (cioè, non dipende da un contesto UI o ASP.NET).
  • Loop di messaggi annidati. Si noti che ciò funzionerà solo se il codice asincrono presuppone solo un contesto a thread singolo, non un tipo di contesto specifico (molte interfacce utente e codice ASP.NET prevedono un contesto specifico).

I loop di messaggi annidati sono i più pericolosi di tutti gli hack, perché causano il re-entrancy . Re-entrancy è estremamente difficile da ragionare, e (IMO) è la causa della maggior parte dei bug di applicazioni su Windows. In particolare, se si è sul thread dell’interfaccia utente e si blocca su una coda di lavoro (in attesa del completamento del lavoro asincrono), il CLR esegue effettivamente alcuni messaggi di pumping per l’utente: gestirà effettivamente alcuni messaggi Win32 dall’interno del proprio codice . Oh, e non hai idea di quali messaggi – quando Chris Brumme dice “Non sarebbe bello sapere esattamente cosa verrà pompato? Sfortunatamente, pompare è un’arte nera che va oltre la comprensione dei mortali”. , quindi non abbiamo davvero alcuna speranza di sapere.

Quindi, quando blocchi in questo modo su un thread dell’interfaccia utente, stai cercando dei problemi. Un’altra citazione interessante dello stesso articolo: “Di tanto in tanto, i clienti all’interno o all’esterno dell’azienda scoprono che stiamo pompando messaggi durante il blocco gestito su un STA [thread UI]. Si tratta di una preoccupazione legittima, perché sanno che è molto difficile scrivere un codice robusto di fronte alla rientranza “.

Sì. Codice molto difficile da scrivere che è robusto di fronte alla rientranza. E i loop di messaggi annidati ti costringono a scrivere un codice che sia solido di fronte alla rientranza. Questo è il motivo per cui la risposta accettata (e più votata) per questa domanda è estremamente pericolosa nella pratica.

Se sei completamente fuori da tutte le altre opzioni – non puoi riprogettare il tuo codice, non puoi ristrutturarlo in modo asincrono – sei costretto dal codice chiamante non modificabile per essere sincronizzato – non puoi cambiare il codice downstream per essere sincronizzato – Non puoi bloccare – non puoi eseguire il codice asincrono su un thread separato – allora e solo allora dovresti considerare di abbracciare la rientranza.

Se ti trovi in ​​questo angolo, ti consiglio di utilizzare qualcosa come Dispatcher.PushFrame per le app WPF , il looping con Application.DoEvents per le app WinForm e, nel caso generale, il mio AsyncContext.Run .

Funziona bene per me

 public static class TaskHelper { public static void RunTaskSynchronously(this Task t) { var task = Task.Run(async () => await t); task.Wait(); } public static T RunTaskSynchronously(this Task t) { T res = default(T); var task = Task.Run(async () => res = await t); task.Wait(); return res; } } 

Se sto leggendo la tua domanda, il codice che vuole la chiamata sincrona a un metodo asincrono è in esecuzione su un thread di dispatcher sospeso. E si desidera effettivamente bloccare in modo sincrono quel thread fino al completamento del metodo async.

I metodi asincroni in C # 5 sono potenziati tagliando efficacemente il metodo in pezzi sotto il cofano e restituendo un Task grado di tracciare il completamento complessivo dell’intero shabang. Tuttavia, il modo in cui i metodi tagliati vengono eseguiti può dipendere dal tipo di espressione passato all’operatore await .

La maggior parte delle volte, await l’ await su un’espressione di tipo Task . L’implementazione del modello di await parte di Task è “intelligente” in quanto rimanda al SynchronizationContext , che in pratica causa quanto segue:

  1. Se il thread che entra await trova su un thread del loop di messaggi Dispatcher o WinForms, assicura che i blocchi del metodo asincrono avvengano come parte dell’elaborazione della coda dei messaggi.
  2. Se il thread che sta entrando await trova su un thread pool di thread, i blocchi rimanenti del metodo async si trovano ovunque nel pool di thread.

Ecco perché probabilmente stai incontrando problemi: l’implementazione del metodo asincrono sta cercando di eseguire il resto sul Dispatcher, anche se è sospesa.

…. backup! ….

Devo porre la domanda, perché stai provando a bloccare in modo sincrono un metodo asincrono? In questo modo si sconfiggerebbe lo scopo sul perché il metodo voleva essere chiamato in modo asincrono. In generale, quando inizi a utilizzare await su un metodo Dispatcher o UI, ti consigliamo di trasformare l’intero stream dell’interfaccia utente asincrono. Ad esempio, se il tuo callstack era simile al seguente:

  1. [Inizio] WebRequest.GetResponse()
  2. YourCode.HelperMethod()
  3. YourCode.AnotherMethod()
  4. YourCode.EventHandlerMethod()
  5. [UI Code].Plumbing() – Codice WPF o WinForms
  6. [Loop dei messaggi]Loop dei messaggi WPF o WinForms

Quindi, una volta che il codice è stato trasformato per utilizzare async, in genere finirai con

  1. [Inizio] WebRequest.GetResponseAsync()
  2. YourCode.HelperMethodAsync()
  3. YourCode.AnotherMethodAsync()
  4. YourCode.EventHandlerMethodAsync()
  5. [UI Code].Plumbing() – Codice WPF o WinForms
  6. [Loop dei messaggi]Loop dei messaggi WPF o WinForms

In realtà rispondendo

La class AsyncHelpers sopra funziona in realtà perché si comporta come un ciclo di messaggi nidificati, ma installa la sua meccanica parallela sul Dispatcher piuttosto che tentare di eseguire sul Dispatcher stesso. Questa è una soluzione per il tuo problema.

Un’altra soluzione alternativa consiste nell’eseguire il metodo asincrono su un thread del threadpool e quindi attendere che venga completato. Fare così è facile – puoi farlo con il seguente frammento:

 var customerList = TaskEx.RunEx(GetCustomers).Result; 

L’API finale sarà Task.Run (…), ma con il CTP avrete bisogno dei suffissi Ex ( spiegazione qui ).

Il modo più semplice che ho trovato per eseguire l’attività in modo sincrono e senza bloccare il thread dell’interfaccia utente è utilizzare RunSynchronously () come:

 Task t = new Task(() => { //.... YOUR CODE .... }); t.RunSynchronously(); 

Nel mio caso, ho un evento che si triggers quando succede qualcosa. Non so quante volte succederà. Quindi, io uso il codice sopra nel mio evento, quindi ogni volta che si triggers, crea un’attività. Le attività vengono eseguite in modo sincrono e funziona perfettamente per me. Sono stato sorpreso che ci sia voluto così tanto tempo per scoprirlo considerando quanto sia semplice. Di solito, le raccomandazioni sono molto più complesse e soggette a errori. Questo è stato semplice e pulito.

L’ho affrontato alcune volte, principalmente nei test di unità o in uno sviluppo di servizi di Windows. Attualmente uso sempre questa funzione:

  var runSync = Task.Factory.StartNew(new Func(async () => { Trace.WriteLine("Task runSync Start"); await TaskEx.Delay(2000); // Simulates a method that returns a task and // inside it is possible that there // async keywords or anothers tasks Trace.WriteLine("Task runSync Completed"); })).Unwrap(); Trace.WriteLine("Before runSync Wait"); runSync.Wait(); Trace.WriteLine("After runSync Waited"); 

È semplice, facile e non ho avuto problemi.

Ho trovato questo codice nel componente Microsoft.AspNet.Identity.Core e funziona.

 private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); // Microsoft.AspNet.Identity.AsyncHelper public static TResult RunSync(Func> func) { CultureInfo cultureUi = CultureInfo.CurrentUICulture; CultureInfo culture = CultureInfo.CurrentCulture; return AsyncHelper._myTaskFactory.StartNew>(delegate { Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = cultureUi; return func(); }).Unwrap().GetAwaiter().GetResult(); } 

Solo una piccola nota: questo approccio:

 Task task = GetCustomers(); task.Wait() 

funziona per WinRT.

Lasciatemi spiegare:

 private void TestMethod() { Task task = GetCustomers(); // call async method as sync and get task as result task.Wait(); // wait executing the method var customer = task.Result; // get's result. Debug.WriteLine(customer.Name); //print customer name } public class Customer { public Customer() { new ManualResetEvent(false).WaitOne(TimeSpan.FromSeconds(5));//wait 5 second (long term operation) } public string Name { get; set; } } private Task GetCustomers() { return Task.Run(() => new Customer { Name = "MyName" }); } 

Inoltre questo approccio funziona solo per le soluzioni di Windows Store!

Nota: questo metodo non è thread-safe se si chiama il metodo all’interno di un altro metodo asincrono (in base ai commenti di @Servy)

In your code, your first wait for task to execute but you haven’t started it so it waits indefinitely. Prova questo:

 Task task = GetCustomers(); task.RunSynchronously(); 

Modificare:

You say that you get an exception. Please post more details, including stack trace.
Mono contains the following test case:

 [Test] public void ExecuteSynchronouslyTest () { var val = 0; Task t = new Task (() => { Thread.Sleep (100); val = 1; }); t.RunSynchronously (); Assert.AreEqual (1, val); } 

Check if this works for you. If it does not, though very unlikely, you might have some odd build of Async CTP. If it does work, you might want to examine what exactly the compiler generates and how Task instantiation is different from this sample.

Edit #2:

I checked with Reflector that the exception you described occurs when m_action is null . This is kinda odd, but I’m no expert on Async CTP. As I said, you should decompile your code and see how exactly Task is being instantiated any how come its m_action is null .


PS What’s the deal with the occasional downvotes? Care to elaborate?

Why not create a call like:

 Service.GetCustomers(); 

that isn’t async.

use below code snip

 Task.WaitAll(Task.Run(async () => await service.myAsyncMethod())); 

This answer is designed for anyone who is using WPF for .NET 4.5.

If you attempt to execute Task.Run() on the GUI thread, then task.Wait() will hang indefinitely, if you do not have the async keyword in your function definition.

This extension method solves the problem by checking to see if we are on the GUI thread, and if so, running the task on the WPF dispatcher thread.

This class can act as the glue between the async/await world and the non-async/await world, in situations where it is unavoidable, such as MVVM properties or dependencies on other APIs that do not use async/await.

 ///  /// Intent: runs an async/await task synchronously. Designed for use with WPF. /// Normally, under WPF, if task.Wait() is executed on the GUI thread without async /// in the function signature, it will hang with a threading deadlock, this class /// solves that problem. ///  public static class TaskHelper { public static void MyRunTaskSynchronously(this Task task) { if (MyIfWpfDispatcherThread) { var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { await task; }); result.Wait(); if (result.Status != DispatcherOperationStatus.Completed) { throw new Exception("Error E99213. Task did not run to completion."); } } else { task.Wait(); if (task.Status != TaskStatus.RanToCompletion) { throw new Exception("Error E33213. Task did not run to completion."); } } } public static T MyRunTaskSynchronously(this Task task) { if (MyIfWpfDispatcherThread) { T res = default(T); var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { res = await task; }); result.Wait(); if (result.Status != DispatcherOperationStatus.Completed) { throw new Exception("Error E89213. Task did not run to completion."); } return res; } else { T res = default(T); var result = Task.Run(async () => res = await task); result.Wait(); if (result.Status != TaskStatus.RanToCompletion) { throw new Exception("Error E12823. Task did not run to completion."); } return res; } } ///  /// If the task is running on the WPF dispatcher thread. ///  public static bool MyIfWpfDispatcherThread { get { return Application.Current.Dispatcher.CheckAccess(); } } } 

Simply calling .Result; or .Wait() is a risk for deadlocks as many have said in comments. Since most of us like oneliners you can use these for .Net 4.5<

Acquiring a value via an async method:

 var result = Task.Run(() => asyncGetValue()).Result; 

Syncronously calling an async method

 Task.Run(() => asyncMethod()).Wait(); 

No deadlock issues will occur due to the use of Task.Run .

Fonte:

https://stackoverflow.com/a/32429753/3850405

I think the following helper method could also solve the problem.

 private TResult InvokeAsyncFuncSynchronously(Func< Task> func) { TResult result = default(TResult); var autoResetEvent = new AutoResetEvent(false); Task.Run(async () => { try { result = await func(); } catch (Exception exc) { mErrorLogger.LogError(exc.ToString()); } finally { autoResetEvent.Set(); } }); autoResetEvent.WaitOne(); return result; } 

Can be used the following way:

 InvokeAsyncFuncSynchronously(Service.GetCustomersAsync); 

You can use CoRoutines . See Caliburn.Micro implementation. I have a custom implementation here .

This is works for me

 using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp2 { public static class AsyncHelper { private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); public static void RunSync(Func func) { _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult(); } public static TResult RunSync(Func> func) { return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult(); } } class SomeClass { public async Task LoginAsync(object loginInfo) { return await Task.FromResult(0); } public object Login(object loginInfo) { return AsyncHelper.RunSync(() => LoginAsync(loginInfo)); //return this.LoginAsync(loginInfo).Result.Content; } } class Program { static void Main(string[] args) { var someClass = new SomeClass(); Console.WriteLine(someClass.Login(1)); Console.ReadLine(); } } } 

On wp8:

Wrap it:

 Task GetCustomersSynchronously() { Task t = new Task(async () => { myCustomers = await GetCustomers(); } t.RunSynchronously(); } 

Call it:

 GetCustomersSynchronously(); 
  private int GetSync() { try { ManualResetEvent mre = new ManualResetEvent(false); int result = null; Parallel.Invoke(async () => { result = await SomeCalcAsync(5+5); mre.Set(); }); mre.WaitOne(); return result; } catch (Exception) { return null; } } 

Or you could just go with:

 customerList = Task.Run>(() => { return GetCustomers(); }).Result; 

For this to compile make sure you reference extension assembly:

 System.Net.Http.Formatting 

Try following code it works for me:

 public async void TaskSearchOnTaskList (SearchModel searchModel) { try { List taskSearchList = await Task.Run( () => MakeasyncSearchRequest(searchModel), cancelTaskSearchToken.Token); if (cancelTaskSearchToken.IsCancellationRequested || string.IsNullOrEmpty(rid_agendaview_search_eventsbox.Text)) { return; } if (taskSearchList == null || taskSearchList[0].result == Constants.ZERO) { RunOnUiThread(() => { textViewNoMembers.Visibility = ViewStates.Visible; taskListView.Visibility = ViewStates.Gone; }); taskSearchRecureList = null; return; } else { taskSearchRecureList = TaskFooterServiceLayer .GetRecurringEvent(taskSearchList); this.SetOnAdapter(taskSearchRecureList); } } catch (Exception ex) { Console.WriteLine("ActivityTaskFooter -> TaskSearchOnTaskList:" + ex.Message); } }