public async void Dispatch() { Outcome <TResult, Exception> outcome; if (realProxy.proxyName != null) { CallLogging.LogStart(realProxy.proxyName, method.Name, args); } object obj; try { obj = method.Invoke(realProxy.target, args); } catch (TargetInvocationException e) { outcome = new Outcome <TResult, Exception>(e.InnerException); goto Finish; } Task <TResult> task = obj as Task <TResult>; if (task == null) { // Can only happen when we chose TResult == Void2 for a method // that actually returns plain Task. // The more obvious task = ((Task)obj).ContinueWith(_ => default(TResult)) // executes outside the synchronization context and posts a continuation // back to the synchronization context, which calls Send, which trips my // assertion in the P# scheduler. The P# task handling needs to change // anyway, but it's fine to keep this version. task = ((Func <Task <TResult> >)(async() => { await(Task) obj; return(default(TResult)); }))(); } // From here to Finish is basically // "Catching<Exception>.AwaitTaskAsync(task)", but such a method // would be prone to misuse and this is the only place we need it, // so inline it here. TResult result; try { result = await task; } catch (Exception ex) { outcome = new Outcome <TResult, Exception>(ex); goto Finish; } outcome = new Outcome <TResult, Exception>(result); Finish: if (realProxy.proxyName != null) { CallLogging.LogEnd(realProxy.proxyName, method.Name, outcome, args); } replyTarget.SetOutcome(outcome); }
public IDisposable Subscribe(IConfigurationSubscriber <TConfig> subscriber, out TConfig currentConfig) { int subscriptionNum = subscriptionCount++; var subscriberProxy = new SubscriberLoggingProxy(subscriber, string.Format("{0} subscriber {1}", proxyName, subscriptionNum)); CallLogging.LogStart(proxyName, nameof(Subscribe), subscriberProxy); // Some mess because of "out" parameter. Does the convenience of // "out" parameters in the common case merit the mess here? var t = LogOutcome(() => { TConfig currentConfig1; var subscriptionProxy1 = new SubscriptionLoggingProxy( original.Subscribe(subscriberProxy, out currentConfig1), string.Format("{0} subscription {1}", proxyName, subscriptionNum)); return(Tuple.Create(currentConfig1, subscriptionProxy1)); }, (outcome) => CallLogging.LogEnd(proxyName, nameof(Subscribe), outcome, subscriberProxy)); currentConfig = t.Item1; return(t.Item2); }
public void Dispose() { CallLogging.LogStart(proxyName, nameof(Dispose)); LogOutcome(() => original.Dispose(), (outcome) => CallLogging.LogEnd(proxyName, nameof(Dispose), outcome)); }
public Task ApplyConfigurationAsync(TConfig newConfig) { CallLogging.LogStart(proxyName, nameof(ApplyConfigurationAsync), newConfig); return(LogOutcomeAsync(() => original.ApplyConfigurationAsync(newConfig), (outcome) => CallLogging.LogEnd(proxyName, nameof(ApplyConfigurationAsync), outcome, newConfig))); }