예제 #1
0
        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)));
 }