c# - How would I run an async Task<T> method synchronously? -


i'm learning async/await, , ran situation need call async method synchronously. how can that?

async method:

public async task<customers> getcustomers() {     return await service.getcustomersasync(); } 

normal usage:

public async void getcustomers() {     customerlist = await getcustomers(); } 

i've tried using following:

task<customer> task = getcustomers(); task.wait()  task<customer> task = getcustomers(); task.runsynchronously();  task<customer> task = getcustomers(); while(task.status != taskstatus.rantocompletion) 

i tried suggestion here, doesn't work when dispatcher in suspended state.

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

here exception , stack trace calling runsynchronously:

system.invalidoperationexception

message: runsynchronously may not called on task unbound delegate.

innerexception: null

source: mscorlib

stacktrace:

          @ system.threading.tasks.task.internalrunsynchronously(taskscheduler scheduler)    @ system.threading.tasks.task.runsynchronously()    @ myapplication.customcontrols.controls.mycustomcontrol.createavailablepanellist() in c:\documents , settings\...\myapplication.customcontrols\controls\mycustomcontrol.xaml.cs:line 638    @ myapplication.customcontrols.controls.mycustomcontrol.get_availablepanels() in c:\documents , settings\...\myapplication.customcontrols\controls\mycustomcontrol.xaml.cs:line 233    @ myapplication.customcontrols.controls.mycustomcontrol.<createopenpanellist>b__36(desktoppanel panel) in c:\documents , settings\...\myapplication.customcontrols\controls\mycustomcontrol.xaml.cs:line 597    @ system.collections.generic.list`1.foreach(action`1 action)    @ myapplication.customcontrols.controls.mycustomcontrol.<createopenpanellist>d__3b.movenext() in c:\documents , settings\...\myapplication.customcontrols\controls\mycustomcontrol.xaml.cs:line 625    @ system.runtime.compilerservices.taskawaiter.<>c__displayclass7.<trysetcontinuationforawait>b__1(object state)    @ system.windows.threading.exceptionwrapper.internalrealcall(delegate callback, object args, int32 numargs)    @ ms.internal.threading.exceptionfilterhelper.trycatchwhen(object source, delegate method, object args, int32 numargs, delegate catchhandler)    @ system.windows.threading.dispatcheroperation.invokeimpl()    @ system.windows.threading.dispatcheroperation.invokeinsecuritycontext(object state)    @ system.threading.executioncontext.runtrycode(object userdata)    @ system.runtime.compilerservices.runtimehelpers.executecodewithguaranteedcleanup(trycode code, cleanupcode backoutcode, object userdata)    @ system.threading.executioncontext.runinternal(executioncontext executioncontext, contextcallback callback, object state)    @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state, boolean ignoresyncctx)    @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state)    @ 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(object o)    @ system.windows.threading.exceptionwrapper.internalrealcall(delegate callback, object args, int32 numargs)    @ ms.internal.threading.exceptionfilterhelper.trycatchwhen(object source, delegate method, object args, int32 numargs, delegate catchhandler)    @ system.windows.threading.dispatcher.invokeimpl(dispatcherpriority priority, timespan timeout, delegate method, object args, int32 numargs)    @ ms.win32.hwndsubclass.subclasswndproc(intptr hwnd, int32 msg, intptr wparam, intptr lparam)    @ ms.win32.unsafenativemethods.dispatchmessage(msg& msg)    @ system.windows.threading.dispatcher.pushframeimpl(dispatcherframe frame)    @ system.windows.threading.dispatcher.pushframe(dispatcherframe frame)    @ system.windows.threading.dispatcher.run()    @ system.windows.application.rundispatcher(object ignore)    @ system.windows.application.runinternal(window window)    @ system.windows.application.run(window window)    @ system.windows.application.run()    @ myapplication.app.main() in c:\documents , settings\...\myapplication\obj\debug\app.g.cs:line 50    @ system.appdomain._nexecuteassembly(runtimeassembly assembly, string[] args)    @ system.appdomain.executeassembly(string assemblyfile, evidence assemblysecurity, string[] args)    @ microsoft.visualstudio.hostingprocess.hostproc.runusersassembly()    @ system.threading.threadhelper.threadstart_context(object state)    @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state, boolean ignoresyncctx)    @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state)    @ system.threading.threadhelper.threadstart() 

here's workaround found works cases (including suspended dispatchers). it's not code , i'm still working understand it, work.

it can called using:

customerlist = asynchelpers.runsync<list<customer>>(() => getcustomers());

code here

public static class asynchelpers {     /// <summary>     /// execute's async task<t> method has void return value synchronously     /// </summary>     /// <param name="task">task<t> method 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;             }                         {                 synch.endmessageloop();             }         }, null);         synch.beginmessageloop();          synchronizationcontext.setsynchronizationcontext(oldcontext);     }      /// <summary>     /// execute's async task<t> method has t return type synchronously     /// </summary>     /// <typeparam name="t">return type</typeparam>     /// <param name="task">task<t> method 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;             }                         {                 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 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) // method threw exeption                     {                         throw new aggregateexception("asynchelpers.run method threw exception.", innerexception);                     }                 }                 else                 {                     workitemswaiting.waitone();                 }             }         }          public override synchronizationcontext createcopy()         {             return this;         }     } } 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -