Como eu poderia executar um método Task asynchronous de forma síncrona?

Estou aprendendo sobre async / await e corri para uma situação onde eu preciso chamar um método asynchronous de forma síncrona. Como eu posso fazer isso?

Método asynchronous:

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

Uso normal:

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

Eu tentei usar o seguinte:

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

Eu também tentei uma sugestão a partir daqui , no entanto, não funciona quando o despachante está em um estado suspenso.

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

Aqui está a exceção e rastreamento de pilha de chamar RunSynchronously :

System.InvalidOperationException

Mensagem : RunSynchronously não pode ser chamado em uma tarefa não vinculada a um delegado.

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

   

    Aqui está uma solução que eu encontrei que funciona para todos os casos (incluindo despachantes suspensos). Não é meu código e ainda estou trabalhando para compreendê-lo completamente, mas funciona.

    Pode ser chamado usando:

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

    O código é daqui

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

    Esteja ciente de que esta resposta é de três anos. Eu escrevi baseado principalmente em uma experiência com .net 4.0, e muito pouco com 4.5 especialmente com async-await . De um modo geral, é uma boa solução simples, mas às vezes quebra as coisas. Por favor, leia a discussão nos comentários.

    .Net 4.5

    Apenas use isto:

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

    Veja: TaskAwaiter , Task.Result , Task.RunSynchronously


    .Net 4.0

    Usa isto:

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

    …ou isto:

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

    Surpreso ninguém mencionou isso:

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

    Não tão bonito quanto alguns dos outros methods aqui, mas tem os seguintes benefícios:

    • não engole exceções (como Wait )
    • Ele não vai envolver quaisquer exceções lançadas em um AggregateException (como Result )
    • funciona para Task e Task ( experimente você mesmo! )

    Além disso, como o GetAwaiter é tipado com duck, isso deve funcionar para qualquer object que seja retornado de um método asynchronous (como ConfiguredAwaitable ou YieldAwaitable ), não apenas Tasks.


    edit: Por favor, note que é possível que esta abordagem (ou usando .Result ) para deadlock, a menos que você tenha certeza de adicionar .ConfigureAwait(false) toda vez que você espera, para todos os methods asynchronouss que podem ser alcançados de BlahAsync() apenas aqueles que chama diretamente). Explicação

     // 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 você é muito preguiçoso para adicionar .ConfigureAwait(false) todos os lugares, e você não se importa com o desempenho que você pode alternativamente fazer

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

    É muito mais simples executar a tarefa no pool de threads, em vez de tentar enganar o agendador para executá-lo em sincronia. Dessa forma, você pode ter certeza de que não será um impasse. O desempenho é afetado por causa da troca 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; 

    Estou aprendendo sobre async / await e corri para uma situação onde eu preciso chamar um método asynchronous de forma síncrona. Como eu posso fazer isso?

    A melhor resposta é que você não , com os detalhes dependentes de qual é a “situação”.

    É um getter / setter de propriedade? Na maioria dos casos, é melhor ter methods asynchronouss do que “propriedades assíncronas”. (Para mais informações, consulte minha postagem no blog sobre propriedades assíncronas ).

    Este é um aplicativo MVVM e você deseja fazer uma vinculação de dados assíncrona? Em seguida, use algo como o meu NotifyTask , conforme descrito no meu artigo do MSDN sobre vinculação de dados assíncrona .

    É um construtor? Então você provavelmente quer considerar um método de fábrica asynchronous. (Para mais informações, consulte minha postagem no blog sobre construtores asynchronouss ).

    Há quase sempre uma resposta melhor do que fazer sync-over-async.

    Se não for possível para a sua situação (e você sabe disso, fazendo uma pergunta aqui descrevendo a situação ), então eu recomendo apenas usando o código síncrono. Async todo o caminho é o melhor; Sincronizar todo o caminho é o segundo melhor. O Sync-over-async não é recomendado.

    No entanto, há um punhado de situações em que o sync-over-async é necessário. Especificamente, você é restrito pelo código de chamada para que você precise ser sincronizado (e não tenha absolutamente nenhuma maneira de repensar ou re-estruturar seu código para permitir assincronia), e você deve chamar o código asynchronous. Esta é uma situação muito rara, mas acontece de tempos em tempos.

    Nesse caso, você precisaria usar um dos hacks descritos no meu artigo sobre desenvolvimento async brownfield , especificamente:

    • Bloqueio (por exemplo, GetAwaiter().GetResult() ). Note que isso pode causar deadlocks (como eu descrevo no meu blog).
    • Executando o código em um thread de pool de threads (por exemplo, Task.Run(..).GetAwaiter().GetResult() ). Observe que isso só funcionará se o código asynchronous puder ser executado em um thread de pool de threads (isto é, não depender de um contexto de interface do usuário ou ASP.NET).
    • Loops de mensagem nesteds. Observe que isso só funcionará se o código asynchronous assumir apenas um contexto de encadeamento único, não um tipo de contexto específico (muitos códigos de interface do usuário e ASP.NET esperam um contexto específico).

    Os loops de mensagens nesteds são os mais perigosos de todos os hacks, porque causam reinput . Re-entrancy é extremamente complicado de raciocinar, e (IMO) é a causa da maioria dos erros de aplicação no Windows. Em particular, se você estiver no thread da interface do usuário e bloquear uma fila de trabalho (aguardando a conclusão do trabalho asynchronous), o CLR realmente enviará mensagens para você – na verdade, ele manipulará algumas mensagens do Win32 código . Ah, e você não tem idéia de quais mensagens – quando Chris Brumme diz: “Não seria ótimo saber exatamente o que será bombeado? Infelizmente, bombear é uma arte negra que está além da compreensão mortal”. então realmente não temos esperança de saber.

    Então, quando você bloqueia assim em um thread de interface do usuário, você está pedindo por problemas. Outra citação do mesmo artigo: “Ocasionalmente, os clientes dentro ou fora da empresa descobrem que estamos bombeando mensagens durante o bloqueio gerenciado em um STA [thread de interface do usuário]. Essa é uma preocupação legítima, porque eles sabem que é muito difícil para escrever código que seja robusto em face da reinput. ”

    Sim. Muito difícil escrever código robusto em face da reinput. E os loops de mensagens nesteds forçam você a escrever um código robusto em face da reinput. É por isso que a resposta aceita (e mais votada) para essa questão é extremamente perigosa na prática.

    Se você está completamente fora de todas as outras opções – você não pode redesenhar seu código, você não pode reestruturá-lo para ser asynchronous – você é forçado por código de chamada imutável a ser sincronizado – você não pode alterar o código downstream para ser sincronizado – você não pode bloquear – você não pode executar o código asynchronous em um tópico separado – então, e somente então , você deve considerar abraçar a reinput.

    Se você se encontrar neste canto, eu recomendaria usar algo como Dispatcher.PushFrame para aplicativos WPF , loop com Application.DoEvents para aplicativos WinForm e, para o caso geral, meu próprio AsyncContext.Run .

    Isso está funcionando bem para mim

     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 eu estiver lendo sua pergunta corretamente – o código que deseja a chamada síncrona para um método asynchronous está sendo executado em um encadeamento de dispatcher suspenso. E você deseja realmente sincronamente bloquear esse segmento até que o método asynchronous seja concluído.

    Os methods asynchronouss no C # 5 são ativados, cortando efetivamente o método em partes sob o capô e retornando uma Task que pode rastrear a conclusão geral de todo o shabang. No entanto, a maneira como os methods cortados podem ser executados pode depender do tipo da expressão passada para o operador await .

    Na maioria das vezes, você estará usando await em uma expressão do tipo Task . A implementação da tarefa do padrão await é “inteligente”, na medida em que é adiada para o SynchronizationContext , o que basicamente faz com que ocorra o seguinte:

    1. Se o encadeamento que está inserindo o await estiver em um encadeamento de loop de mensagens Dispatcher ou WinForms, ele garantirá que os fragments do método asynchronous ocorram como parte do processamento da fila de mensagens.
    2. Se o encadeamento que está inserindo o await estiver em um encadeamento do pool de encadeamentos, os trechos restantes do método asynchronous ocorrerão em qualquer lugar no pool de encadeamentos.

    É por isso que você provavelmente está tendo problemas – a implementação do método asynchronous está tentando executar o restante no Dispatcher – mesmo que esteja suspenso.

    …. recuando! ….

    Eu tenho que fazer a pergunta, por que você está tentando bloquear de forma síncrona em um método asynchronous? Fazer isso seria frustrar o propósito de por que o método queria ser chamado de forma assíncrona. Em geral, quando você começar a usar o await em um Dispatcher ou um método de UI, você desejará transformar todo o stream de sua interface do usuário como asynchronous. Por exemplo, se a sua pilha de chamadas for algo como o seguinte:

    1. [Início] WebRequest.GetResponse()
    2. YourCode.HelperMethod()
    3. YourCode.AnotherMethod()
    4. YourCode.EventHandlerMethod()
    5. [UI Code].Plumbing()WPF ou código WinForms
    6. [Loop de mensagem]WPF ou loop de mensagem do WinForms

    Então, uma vez que o código foi transformado para usar async, você normalmente acabará com

    1. [Início] WebRequest.GetResponseAsync()
    2. YourCode.HelperMethodAsync()
    3. YourCode.AnotherMethodAsync()
    4. YourCode.EventHandlerMethodAsync()
    5. [UI Code].Plumbing()WPF ou código WinForms
    6. [Loop de mensagem]WPF ou loop de mensagem do WinForms

    Respondendo realmente

    A class AsyncHelpers acima, na verdade, funciona porque se comporta como um loop de mensagem nested, mas instala sua própria mecânica paralela ao Dispatcher em vez de tentar executar no próprio Dispatcher. Essa é uma solução para o seu problema.

    Outra solução é executar seu método asynchronous em um thread de threadpool e, em seguida, aguarde a conclusão. Fazer isso é fácil – você pode fazer isso com o seguinte snippet:

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

    A API final será Task.Run (…), mas com o CTP você precisará dos sufixos Ex ( explicação aqui ).

    A maneira mais simples que eu encontrei para executar a tarefa de forma síncrona e sem bloquear o thread da interface do usuário é usar RunSynchronously () como:

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

    No meu caso, tenho um evento que é acionado quando algo ocorre. Eu não sei quantas vezes isso ocorrerá. Então, eu uso código acima no meu evento, então sempre que ele é acionado, ele cria uma tarefa. Tarefas são executadas de forma síncrona e funciona muito bem para mim. Fiquei surpreso que demorei tanto tempo para descobrir isso, considerando o quão simples é. Geralmente, as recomendações são muito mais complexas e propensas a erros. Isto foi, é simples e limpo.

    Eu já o enfrentei algumas vezes, principalmente em testes de unidade ou em um desenvolvimento de serviço do Windows. Atualmente eu sempre uso esse recurso:

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

    É simples, fácil e não tive problemas.

    Eu encontrei este código no componente Microsoft.AspNet.Identity.Core, e 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(); } 

    Apenas uma pequena nota – esta abordagem:

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

    funciona para o WinRT.

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

    Além disso, esta abordagem funciona apenas para as soluções da Windows Store!

    Nota: Este caminho não é thread safe se você chamar seu método dentro de outro método asynchronous (de acordo com comentários de @Servy)

    Em seu código, sua primeira espera pela execução da tarefa, mas você não a iniciou, para que ela espere indefinidamente. Tente isto:

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

    Editar:

    Você diz que você recebe uma exceção. Por favor, poste mais detalhes, incluindo rastreamento de pilha.
    Mono contém o seguinte caso de teste:

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

    Verifique se isso funciona para você. Se isso não acontecer, apesar de muito improvável, você pode ter uma versão estranha do CTP Assíncrono. Se funcionar, talvez você queira examinar o que exatamente o compilador gera e como Task instanciação de Task é diferente dessa amostra.

    Editar # 2:

    Eu verifiquei com o Reflector que a exceção que você descreveu ocorre quando m_action é null . Isso é meio estranho, mas eu não sou especialista em CTP Assíncrono. 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(); } 

    Chame-o:

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