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(); } 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); // Set the disposable disposer.Set(subscription); return(tcs.Task); }
internal static Task <T> ReceiveAsync <T>(this IMessageBus bus, ISubscriber subscriber, string cursor, CancellationToken cancel, int maxMessages, Func <MessageResult, T> map) where T : class { var tcs = new TaskCompletionSource <T>(); IDisposable subscription = null; var disposer = new Disposer(); int resultSet = 0; var result = default(T); IDisposable registration = null; registration = cancel.SafeRegister(state => { state.Dispose(); }, disposer); 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(); } if (messageResult.Terminal) { Interlocked.CompareExchange(ref result, map(messageResult), null); // 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); }