public static IAsyncObservable <TResult> GroupJoin <TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IAsyncObservable <TLeft> left, IAsyncObservable <TRight> right, Func <TLeft, IAsyncObservable <TLeftDuration> > leftDurationSelector, Func <TRight, IAsyncObservable <TRightDuration> > rightDurationSelector, Func <TLeft, IAsyncObservable <TRight>, TResult> resultSelector) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (leftDurationSelector == null) { throw new ArgumentNullException(nameof(leftDurationSelector)); } if (rightDurationSelector == null) { throw new ArgumentNullException(nameof(rightDurationSelector)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } return(Create <TResult>(async observer => { var subscriptions = new CompositeAsyncDisposable(); var(leftObserver, rightObserver, disposable) = AsyncObserver.GroupJoin(observer, subscriptions, leftDurationSelector, rightDurationSelector, resultSelector); var leftSubscription = await left.SubscribeSafeAsync(leftObserver).ConfigureAwait(false); await subscriptions.AddAsync(leftSubscription).ConfigureAwait(false); var rightSubscription = await right.SubscribeSafeAsync(rightObserver).ConfigureAwait(false); await subscriptions.AddAsync(rightSubscription).ConfigureAwait(false); return disposable; })); }