Friday 15 August 2014

c# - EntLib TransientFaultHandling RetryPolicy.ExecuteAsync synchronization context -



c# - EntLib TransientFaultHandling RetryPolicy.ExecuteAsync synchronization context -

i'm using enterprise library transient fault handling application block in windows 8 store app wcf info services client odata. want utilize retry logic transient errors occurring when calling odata service. built custom transient error detection strategy.

i have built loadtaskasync extension method dataservicecollection loadasync method not homecoming task (instead dataservicecollection raises loadcompleted event).

so can load info dataservicecollection follows:

var query = this.datacontext.products.where(item => item.modified >= anchor); var products = new dataservicecollection<product>(this.datacontext); await this.retrypolicy.executeasync(() => products.loadtaskasync(query));

now documentation enterprise library transient fault handling application block states

the taskfunc argument pass executeasync method not invoked in same synchronization context used when calling executeasync originally; if need start task within ui thread example, sure schedule explicitly within delegate.

i need invoke loadtaskasync method on ui thread load operation may update products tracked info context , info bound ui.

question how? preferably without modifying loadtaskasync extension method (what if not code change). thinking of creating extension method retrypolicy calls executeasync method while making sure taskfunc invoked on ui thread.

the easiest way perhaps modify loadtaskasync extension method pass in taskcreationoptions.attachedtoparent, create extension method retrypolicy follows:

public static task<tresult> executecurrentsynchronizationcontextasync<tresult>( retrypolicy retrypolicy, func<taskcreationoptions, task<tresult>> taskfunc) { var scheduler = taskscheduler.fromcurrentsynchronizationcontext(); homecoming retrypolicy.executeasync( () => task.factory.startnew( () => taskfunc(taskcreationoptions.attachedtoparent), cancellationtoken.none, taskcreationoptions.none, scheduler).unwrap()); }

note taskfunc must func<taskcreationoptions, task<tresult>>.

i phone call follows:

await this.retrypolicy.executecurrentsynchronizationcontextasync( creationoptions => products.loadtaskasync(query, creationoptions));

as prefer not alter loadtaskasync extension method, how alter retrypolicy executecurrentsynchronizationcontextasync extension method taskfunc can func<task<tresult>> 1 time again while making sure taskfunc invoked on ui thread?

i not recommend using attachedtoparent asynchronous tasks. in fact, promise-style tasks specify denychildattach prevents attachedtoparent working.

instead, need capture synchronization context , utilize that. there wrinkle: windows store apps don't allow synchronous invocation on synchronization context, you'll need either utilize coredispatcher.runasync instead of synchronizationcontext, or build own async-aware extension method synchronizationcontext. of two, prefer using synchronizationcontext approach; it's bit more code in case, means don't have tie code (presumably service-layer code) specific ui framework.

so, first define runasync on synchronizationcontext, (asynchronously) execute asynchronous code on specified synchronization context:

public static task<tresult> runasync<tresult>(this synchronizationcontext context, func<task<tresult>> func) { var tcs = new taskcompletionsource<tresult>(); context.post(async _ => { seek { tcs.trysetresult(await func()); } grab (operationcanceledexception) { tcs.trysetcanceled(); } grab (exception ex) { tcs.trysetexception(ex); } }, null); homecoming tcs.task; }

then can capture , utilize synchronizationcontext:

public static task<tresult> executeoncurrentsynchronizationcontextasync<tresult>( retrypolicy retrypolicy, func<task<tresult>> taskfunc) { var context = synchronizationcontext.current ?? new synchronizationcontext(); homecoming retrypolicy.executeasync(() => context.runasync(taskfunc)); }

c# asynchronous task-parallel-library async-await wcf-data-services

No comments:

Post a Comment