C# 如何运行异步任务<;T>;方法同步?

C# 如何运行异步任务<;T>;方法同步?,c#,asynchronous,c#-5.0,async-await,C#,Asynchronous,C# 5.0,Async Await,我正在学习async/await,遇到了需要同步调用异步方法的情况。我该怎么做 异步方法: public async Task<Customers> GetCustomers() { return await Service.GetCustomersAsync(); } var result = Task.Run(() => asyncGetValue()).Result; 我尝试使用以下方法: Task<Customer> task = GetCust

我正在学习async/await,遇到了需要同步调用异步方法的情况。我该怎么做

异步方法:

public async Task<Customers> GetCustomers()
{
    return await Service.GetCustomersAsync();
}
var result = Task.Run(() => asyncGetValue()).Result;
我尝试使用以下方法:

Task<Customer> task = GetCustomers();
task.Wait()

Task<Customer> task = GetCustomers();
task.RunSynchronously();

Task<Customer> task = GetCustomers();
while(task.Status != TaskStatus.RanToCompletion)
以下是调用
RunSynchronously
的异常和堆栈跟踪:

System.InvalidOperationException异常

消息:不能对未绑定到委托的任务调用RunSynchronously

内部异常:空

来源:mscorlib

堆栈跟踪

at System.Threading.Tasks.Task.InternalRunSynchronously(任务调度器)
在System.Threading.Tasks.Task.RunSynchronously()中
在C:\Documents and Settings\…\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs中的MyApplication.CustomControls.Controls.MyCustomControl.CreateAvaailablePanelList()中:第638行
在C:\Documents and Settings\…\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs中的MyApplication.CustomControls.Controls.MyCustomControl.get\u AvailablePanels()中
在C:\Documents and Settings\…\MyApplication.CustomControls\Controls\MyCustomControls.xaml.cs中的MyApplication.CustomControls.Controls.MyCustomControls.b_u36(桌面面板)中:第597行
at System.Collections.Generic.List`1.ForEach(操作`1操作)
在C:\Documents and Settings\…\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs中的MyApplication.CustomControls.Controls.MyCustomControl.d_3b.MoveNext()处:第625行
at System.Runtime.CompilerServices.TaskAwaiter.c__显示类7.b__1(对象状态)
位于System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托回调、对象参数、Int32 numArgs)
位于MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象源、委托方法、对象参数、Int32 numArgs、委托catchHandler)
在System.Windows.Threading.DispatcherOperation.InvokeImpl()中
位于System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(对象状态)
位于System.Threading.ExecutionContext.runTryCode(对象用户数据)
在System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode代码、CleanupCode backoutCode、Object userData)中运行
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔ignoreSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
在System.Windows.Threading.DispatcherOperation.Invoke()中
在System.Windows.Threading.Dispatcher.ProcessQueue()中
位于System.Windows.Threading.Dispatcher.WndProcHook(IntPtr-hwnd、Int32-msg、IntPtr-wParam、IntPtr-lParam、Boolean和handled)
在MS.Win32.HwndWrapper.WndProc(IntPtr-hwnd、Int32-msg、IntPtr-wParam、IntPtr-lParam、Boolean和handled)
在MS.Win32.HwndSubclass.DispatcherCallbackOperation(对象o)上
位于System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托回调、对象参数、Int32 numArgs)
位于MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象源、委托方法、对象参数、Int32 numArgs、委托catchHandler)
位于System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority优先级、TimeSpan超时、委托方法、对象参数、Int32 numArgs)
位于MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd、Int32 msg、IntPtr wParam、IntPtr lParam)
位于MS.Win32.unsafentivemethods.DispatchMessage(MSG&MSG)
位于System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame框架)
在System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame框架)上
在System.Windows.Threading.Dispatcher.Run()中
位于System.Windows.Application.RunDispatcher(对象忽略)
位于System.Windows.Application.RunInternal(窗口)
在System.Windows.Application.Run(窗口)中
在System.Windows.Application.Run()处
在C:\Documents and Settings\…\MyApplication\obj\Debug\App.g.cs中的MyApplication.App.Main()处:第50行
位于System.AppDomain.\u nExecuteAssembly(RuntimeAssembly程序集,字符串[]args)
位于System.AppDomain.ExecuteAssembly(字符串汇编文件、证据汇编安全性、字符串[]args)
在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()上
位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔ignoreSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
位于System.Threading.ThreadHelper.ThreadStart()处

为什么不创建一个调用,如:

Service.GetCustomers();

这不是异步的。

在您的代码中,您的第一个等待任务执行,但您尚未启动它,因此它会无限期地等待。试试这个:

Task<Customer> task = GetCustomers();
task.RunSynchronously();
检查这是否适合你。如果没有,尽管可能性不大,您可能会有一些奇怪的异步CTP构建。如果它确实起作用,您可能需要检查编译器究竟生成了什么,以及
任务
实例化与此示例有何不同

编辑#2:


我通过Reflector检查,您描述的异常发生在
m_action
null
时。这有点奇怪,但我不是异步CTP方面的专家。正如我所说,你应该反编译你的代码,看看
任务
是如何被实例化的。为什么它的
m_动作
null

我发现了一个解决方法,适用于所有情况(包括挂起的调度程序)。这不是我的代码,我仍在努力完全理解它,但它确实有效

可以使用以下方法调用它:

customerList=asynchhelpers.RunSync(()=>GetCustomers())

代码来自

公共静态类Asyn
Service.GetCustomers();
Task<Customer> task = GetCustomers();
task.RunSynchronously();
[Test]
public void ExecuteSynchronouslyTest ()
{
        var val = 0;
        Task t = new Task (() => { Thread.Sleep (100); val = 1; });
        t.RunSynchronously ();

        Assert.AreEqual (1, val);
}
public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task<T> method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task<T> method to execute</param>
    public static void RunSync(Func<Task> 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);
    }

    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> 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<Tuple<SendOrPostCallback, object>> items =
            new Queue<Tuple<SendOrPostCallback, object>>();

        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<SendOrPostCallback, object> 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;
        }
    }
}
var customerList = TaskEx.RunEx(GetCustomers).Result;
Task<Customer> task = GetCustomers();
task.Wait()
private void TestMethod()
{
    Task<Customer> 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<Customer> GetCustomers()
{
    return Task.Run(() => new Customer
    {
        Name = "MyName"
    });
}
// For Task<T>: will block until the task is completed...
var result = task.Result; 

// For Task (not Task<T>): will block until the task is completed...
task2.RunSynchronously();
var x = (IAsyncResult)task;
task.Start();

x.AsyncWaitHandle.WaitOne();
task.Start();
task.Wait();
Task GetCustomersSynchronously()
{
    Task t = new Task(async () =>
    {
        myCustomers = await GetCustomers();
    }
    t.RunSynchronously();
}
GetCustomersSynchronously();
Task<MyResult> DoSomethingAsync() { ... }

// Starts the asynchronous task on a thread-pool thread.
// Returns a proxy to the original task.
Task<MyResult> task = Task.Run(() => DoSomethingAsync());

// Will block until the task is completed...
MyResult result = task.Result; 
    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;
        }
    }
        var runSync = Task.Factory.StartNew(new Func<Task>(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");
public static class TaskHelper
{
    public static void RunTaskSynchronously(this Task t)
    {
        var task = Task.Run(async () => await t);
        task.Wait();
    }

    public static T RunTaskSynchronously<T>(this Task<T> t)
    {
        T res = default(T);
        var task = Task.Run(async () => res = await t);
        task.Wait();
        return res;
    }
}
/// <summary>
///     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.
/// </summary>
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<T>(this Task<T> 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;
        }
    }

    /// <summary>
    ///     If the task is running on the WPF dispatcher thread.
    /// </summary>
    public static bool MyIfWpfDispatcherThread
    {
        get
        {
            return Application.Current.Dispatcher.CheckAccess();
        }
    }
}
private static readonly TaskFactory _myTaskFactory = new 
     TaskFactory(CancellationToken.None, TaskCreationOptions.None, 
     TaskContinuationOptions.None, TaskScheduler.Default);

// Microsoft.AspNet.Identity.AsyncHelper
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
    CultureInfo cultureUi = CultureInfo.CurrentUICulture;
    CultureInfo culture = CultureInfo.CurrentCulture;
    return AsyncHelper._myTaskFactory.StartNew<Task<TResult>>(delegate
    {
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = cultureUi;
        return func();
    }).Unwrap<TResult>().GetAwaiter().GetResult();
}
public async void TaskSearchOnTaskList (SearchModel searchModel)
{
    try
    {
        List<EventsTasksModel> 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);
    }
}
public Task<int> BlahAsync()
{
    // ...
}

int result = BlahAsync().GetAwaiter().GetResult();
// 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.
Task.Run(() => BlahAsync()).GetAwaiter().GetResult()
private TResult InvokeAsyncFuncSynchronously<TResult>(Func< Task<TResult>> 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;
    }
InvokeAsyncFuncSynchronously(Service.GetCustomersAsync);
customerList = Task.Run<List<Customer>>(() => { return GetCustomers(); }).Result;
System.Net.Http.Formatting
Task.WaitAll(Task.Run(async () => await service.myAsyncMethod()));
Task t = new Task(() => 
{ 
   //.... YOUR CODE ....
});
t.RunSynchronously();
var result = Task.Run(() => asyncGetValue()).Result;
Task.Run(() => asyncMethod()).Wait();
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<Task> func)
        {
            _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
        }

        public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        {
            return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
        }
    }

    class SomeClass
    {
        public async Task<object> 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();
        }
    }
}
Task DoSomeWork();
Task.Run(async () => await DoSomeWork()).Wait();
Task<T> GetSomeValue();
var result = Task.Run(() => GetSomeValue()).Result;
var task = Task.Run(()=>DoSomethingAsyncronous());

if(!SpinWait.SpinUntil(()=>task.IsComplete, TimeSpan.FromSeconds(30)))
{//Task didn't complete within 30 seconds, fail...
   return false;
}

return true;
var customers = GetCustomersAsync().GetAwaiter().GetResult();