¿Cómo ejecutaría un método Async Task sincrónicamente?

Estoy aprendiendo acerca de async / await, y me encontré con una situación en la que necesito llamar a un método asíncrono sincrónicamente. ¿Cómo puedo hacer eso?

Método Async:

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

Uso normal:

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

He intentado usar lo siguiente:

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

También probé una sugerencia desde aquí , sin embargo, no funciona cuando el despachador está suspendido.

 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(); } 

Aquí está la excepción y el seguimiento de la stack de llamar a RunSynchronously :

System.InvalidOperationException

Mensaje : RunSynchronously no se puede invocar en una tarea unbound a un delegado.

InnerException : null

Fuente : 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() 

Aquí hay una solución alternativa que encontré que funciona para todos los casos (incluidos los despachadores suspendidos). No es mi código y todavía estoy trabajando para entenderlo completamente, pero funciona.

Se puede llamar usando:

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

El código es de aquí

 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; } } } 

Tenga en cuenta que esta respuesta tiene tres años. Lo escribí basado principalmente en una experiencia con .Net 4.0, y muy poco con 4.5 especialmente con async-await . En términos generales, es una solución sencilla y agradable, pero a veces rompe las cosas. Por favor lea la discusión en los comentarios.

.Net 4.5

Solo usa esto:

 // 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(); 

Ver: TaskAwaiter , Task.Result , Task.RunSynchronously


.Net 4.0

Utilizar esta:

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

…o esto:

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

Sorprendido, nadie mencionó esto:

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

No es tan bonito como algunos de los otros métodos aquí, pero tiene los siguientes beneficios:

  • no traga excepciones (como Wait )
  • no ajustará ninguna excepción lanzada en una AggregateException (como Result )
  • funciona tanto para Task como para Task (¡ pruébalo tú mismo! )

Además, dado que GetAwaiter está escrito en pato, esto debería funcionar para cualquier objeto que se devuelva desde un método asíncrono (como ConfiguredAwaitable o YieldAwaitable ), no solo Tareas.


editar: tenga en cuenta que es posible que este método (o el uso de .Result ) se .Result , a menos que se asegure de agregar .ConfigureAwait(false) cada vez que lo espere, para todos los métodos asíncronos que posiblemente se puedan obtener desde BlahAsync() (no solo los llama directamente). Explicación

 // 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. 

Si eres demasiado perezoso para agregar .ConfigureAwait(false) todas partes, y no te importa el rendimiento, puedes hacerlo alternativamente

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

Es mucho más simple ejecutar la tarea en el grupo de subprocesos, en lugar de intentar engañar al progtwigdor para que lo ejecute de forma síncrona. De esta forma, puedes estar seguro de que no se estancará. El rendimiento se ve afectado por el cambio de contexto.

 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; 

Estoy aprendiendo acerca de async / await, y me encontré con una situación en la que necesito llamar a un método asíncrono sincrónicamente. ¿Cómo puedo hacer eso?

La mejor respuesta es que no , y los detalles dependen de la “situación”.

¿Es un getter / setter de la propiedad? En la mayoría de los casos, es mejor tener métodos asíncronos que “propiedades asíncronas”. (Para obtener más información, consulte la publicación de mi blog sobre propiedades asincrónicas ).

¿Es esta una aplicación MVVM y quieres hacer un enlace de datos asíncrono? A continuación, utilice algo como NotifyTask , como se describe en mi artículo de MSDN sobre el enlace de datos asincrónico .

¿Es un constructor? Entonces probablemente desee considerar un método de fábrica asincrónico. (Para obtener más información, consulte la publicación de mi blog sobre constructores asincrónicos ).

Casi siempre hay una mejor respuesta que hacer sincronización sincronizada.

Si no es posible para su situación (y lo sabe al hacer una pregunta aquí que describe la situación ), le recomendaría usar código síncrono. Async todo el camino es mejor; sincronizar todo el camino es el segundo mejor. Sync-over-async no es recomendable.

Sin embargo, hay un puñado de situaciones en las que es necesaria la sincronización por sincronización. Específicamente, está restringido por el código de llamada para que tenga que sincronizarse (y no tenga absolutamente ninguna manera de volver a pensar o de reestructurar su código para permitir la asincronía), y debe llamar al código asíncrono. Esta es una situación muy rara, pero aparece de vez en cuando.

En ese caso, necesitaría usar uno de los hacks descritos en mi artículo sobre el desarrollo async brownfield , específicamente:

  • Bloqueo (por ejemplo, GetAwaiter().GetResult() ). Tenga en cuenta que esto puede causar interlockings (como describo en mi blog).
  • Ejecutando el código en un subproceso de grupo de subprocesos (por ejemplo, Task.Run(..).GetAwaiter().GetResult() ). Tenga en cuenta que esto solo funcionará si el código asíncrono se puede ejecutar en un subproceso de grupo de subprocesos (es decir, no depende de un contexto de UI o ASP.NET).
  • Bucles de mensajes nesteds. Tenga en cuenta que esto solo funcionará si el código asíncrono solo asume un contexto de subproceso único, no un tipo de contexto específico (una gran cantidad de código UI y ASP.NET esperan un contexto específico).

Los bucles de mensajes nesteds son los más peligrosos de todos los hacks, porque provocan la reentrada . La reentrada es extremadamente difícil de razonar, y (IMO) es la causa de la mayoría de los errores de aplicación en Windows. En particular, si está en el hilo de la interfaz de usuario y bloquea en una cola de trabajo (esperando a que se complete el trabajo asincrónico), entonces el CLR en realidad hace un mensaje de bombeo para usted – realmente manejará algunos mensajes de Win32 desde su código . Ah, y no tienes idea qué mensajes, cuando Chris Brumme dice: “¿No sería genial saber exactamente qué se bombeará? Desafortunadamente, el bombeo es un arte negro que está más allá de la comprensión mortal”. , entonces realmente no tenemos esperanza de saber.

Entonces, cuando bloqueas así en un hilo de interfaz de usuario, estás buscando problemas. Otra cita del mismo artículo: “De vez en cuando, los clientes dentro o fuera de la compañía descubren que estamos transfiriendo mensajes durante el locking administrado en un STA [UI thread]. Esta es una preocupación legítima, porque saben que es muy difícil para escribir código que sea robusto frente a la reentrada “.

Sí lo es. Código muy difícil de escribir que es robusto frente a la reentrada. Y los bucles de mensajes nesteds lo obligan a escribir código que es robusto frente a la reentrada. Esta es la razón por la cual la respuesta aceptada (y la más votada) para esta pregunta es extremadamente peligrosa en la práctica.

Si está completamente fuera de todas las demás opciones, no puede rediseñar su código, no puede reestructurarlo para que sea asíncrono, el código de llamada inmutable le obliga a sincronizar, no puede cambiar el código de flujo descendente para sincronizarlo – no se puede bloquear – no se puede ejecutar el código asíncrono en un hilo separado – entonces y solo entonces debería considerar aceptar la reentrada.

Si se encuentra en esta esquina, le recomendaría utilizar algo como Dispatcher.PushFrame para aplicaciones WPF , bucles con Application.DoEvents para aplicaciones WinForm y, en general, mi propia AsyncContext.Run .

Esto está funcionando bien para mí

 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; } } 

Si estoy leyendo correctamente su pregunta, el código que desea la llamada síncrona a un método asíncrono se está ejecutando en una cadena suspendida suspendida. Y desea bloquear sincrónicamente ese subproceso hasta que se complete el método async.

Los métodos asíncronos en C # 5 se alimentan cortando eficazmente el método en piezas bajo el capó, y devolviendo una Task que puede rastrear la finalización total de todo el shabang. Sin embargo, la forma en que se ejecutan los métodos fragmentados puede depender del tipo de expresión pasada al operador await .

La mayoría de las veces, usará await en una expresión de tipo Task . La implementación de Task del patrón await es “inteligente” en cuanto difiere al SynchronizationContext , que básicamente hace que ocurra lo siguiente:

  1. Si el hilo que ingresa a la await está en un hilo de bucle de mensaje de Dispatcher o WinForms, garantiza que los fragmentos del método async ocurran como parte del procesamiento de la cola de mensajes.
  2. Si el subproceso que ingresa a la await está en una cadena de subprocesos, los trozos restantes del método asincrónico ocurren en cualquier parte del grupo de subprocesos.

Es por eso que probablemente tenga problemas: la implementación del método asincrónico está intentando ejecutar el rest en el Dispatcher, aunque esté suspendido.

…. retrocediendo! ….

Tengo que hacer la pregunta, ¿por qué intentas bloquear sincrónicamente un método asíncrono? Si lo hace, vencerá el propósito de por qué el método quería ser llamado asincrónicamente. En general, cuando empiece a utilizar await en un método Dispatcher o UI, querrá convertir el flujo de UI completo en asincrónico. Por ejemplo, si su stack de llamadas fue algo como lo siguiente:

  1. [Arriba] WebRequest.GetResponse()
  2. YourCode.HelperMethod()
  3. YourCode.AnotherMethod()
  4. YourCode.EventHandlerMethod()
  5. [UI Code].Plumbing() – Código WPF o WinForms
  6. [Message Loop]WPF o WinForms Message Loop

Luego, una vez que el código se ha transformado para usar asincrónico, generalmente terminará con

  1. [Arriba] WebRequest.GetResponseAsync()
  2. YourCode.HelperMethodAsync()
  3. YourCode.AnotherMethodAsync()
  4. YourCode.EventHandlerMethodAsync()
  5. [UI Code].Plumbing() – Código WPF o WinForms
  6. [Message Loop]WPF o WinForms Message Loop

En realidad respondiendo

La clase AsyncHelpers anterior en realidad funciona porque se comporta como un bucle de mensajes nesteds, pero instala su propia mecánica paralela al Dispatcher en lugar de intentar ejecutar en el propio Dispatcher. Esa es una solución para su problema.

Otra solución consiste en ejecutar su método async en una secuencia de subprocesos y luego esperar a que se complete. Hacerlo es fácil: puedes hacerlo con el siguiente fragmento:

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

La API final será Task.Run (…), pero con CTP necesitarás los sufijos Ex ( explicación aquí ).

La forma más sencilla que he encontrado para ejecutar tareas de forma síncrona y sin bloquear el hilo de UI es utilizar RunSynchronously () como:

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

En mi caso, tengo un evento que se activa cuando ocurre algo. No sé cuántas veces ocurrirá. Por lo tanto, uso el código anterior en mi evento, por lo que cada vez que se dispara, crea una tarea. Las tareas se ejecutan de forma sincrónica y funciona muy bien para mí. Me sorprendió que me llevara tanto tiempo descubrir esto considerando lo simple que es. Por lo general, las recomendaciones son mucho más complejas y propensas a errores. Esto fue simple y limpio.

Lo he enfrentado varias veces, principalmente en pruebas unitarias o en un desarrollo de servicios de Windows. Actualmente siempre uso esta característica:

  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"); 

Es simple, fácil y no tuve problemas.

Encontré este código en el componente Microsoft.AspNet.Identity.Core, y funciona.

 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 pequeña nota: este enfoque:

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

funciona para WinRT.

Dejame explicar:

 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" }); } 

¡Además, este enfoque solo funciona para las soluciones de Windows Store!

Nota: De esta manera no es seguro para subprocesos si llama a su método dentro de otro método asíncrono (según los comentarios de @Servy)

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

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

Editar:

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? ¿Cuidado para elaborar?

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 .

Fuente:

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); } }