Пример #1
0
        public static Task <T> ReceiveAsync <T>(this IMessageBus bus,
                                                ISubscriber subscriber,
                                                string cursor,
                                                CancellationToken cancel,
                                                int maxMessages,
                                                Func <MessageResult, T> map,
                                                Action <MessageResult, T> end) where T : class
        {
            var         tcs          = new TaskCompletionSource <T>();
            IDisposable subscription = null;

            var disposer     = new Disposer();
            int resultSet    = 0;
            var result       = default(T);
            var registration = default(CancellationTokenRegistration);

            try
            {
                registration = cancel.Register(disposer.Dispose);
            }
            catch (ObjectDisposedException)
            {
                // Dispose immediately
                disposer.Dispose();
            }

            try
            {
                subscription = bus.Subscribe(subscriber, cursor, messageResult =>
                {
                    // Mark the flag as set so we only set the result once
                    if (Interlocked.Exchange(ref resultSet, 1) == 0)
                    {
                        result = map(messageResult);

                        // Dispose of the cancellation token subscription
                        registration.Dispose();

                        // Dispose the subscription
                        disposer.Dispose();
                    }

                    if (messageResult.Terminal)
                    {
                        Interlocked.CompareExchange(ref result, map(messageResult), null);

                        // Fire a callback before the result is set
                        end(messageResult, result);

                        // Set the result
                        tcs.TrySetResult(result);
                    }

                    return(TaskAsyncHelper.False);
                },
                                             maxMessages);
            }
            catch (Exception ex)
            {
                tcs.TrySetException(ex);

                registration.Dispose();

                return(tcs.Task);
            }

            // Set the disposable
            disposer.Set(subscription);

            return(tcs.Task);
        }