public static Task <ConsumeContext <T> > SubscribeHandler <T>(this IBus bus, TimeSpan?timeout = null, CancellationToken cancelToken = default) where T : class { if (bus == null) { throw new ArgumentNullException(nameof(bus)); } if (timeout.HasValue && timeout < Timeout.InfiniteTimeSpan) { throw new ArgumentOutOfRangeException(nameof(timeout)); } ConnectHandle handler = null; var cts = CancellationTokenSource.CreateLinkedTokenSource(cancelToken); var lnkCancelToken = cts.Token; var tcs = new TaskCompletionSource <ConsumeContext <T> >(); if (timeout.HasValue && timeout.Value != Timeout.InfiniteTimeSpan) { cts.CancelAfter((new TimeSpan[] { timeout.Value, TimeSpan.FromMilliseconds(1000) }).Max()); } handler = bus.ConnectHandler <T>(context => { cts.Dispose(); if (tcs.TrySetResult(context)) { handler.Disconnect(); } return(Task.CompletedTask); }); if (!tcs.Task.IsCompleted) { lnkCancelToken.Register(() => { cts.Dispose(); if (tcs.TrySetCanceled()) { handler.Disconnect(); } }); } return(tcs.Task); }