Ver código fonte

Merge pull request #170 from aelij/asyncawait

Using async/await in System.Interactive.Async
Oren Novotny 9 anos atrás
pai
commit
3e5db62d16

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 0
Ix.NET/Source/Ix.NET.sln.DotSettings


Diferenças do arquivo suprimidas por serem muito extensas
+ 443 - 688
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Aggregates.cs


+ 15 - 29
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Conversions.cs

@@ -3,7 +3,6 @@
 // See the LICENSE file in the project root for more information. 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Threading.Tasks;
 using System.Threading;
 
@@ -14,16 +13,16 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IEnumerable<TSource> source)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
 
             return Create(() =>
             {
                 var e = source.GetEnumerator();
 
                 return Create(
-                    ct => Task.Factory.StartNew(() =>
+                    ct => Task.Run(() =>
                     {
-                        var res = default(bool);
+                        var res = false;
                         try
                         {
                             res = e.MoveNext();
@@ -44,7 +43,7 @@ namespace System.Linq
         public static IEnumerable<TSource> ToEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
 
             return ToEnumerable_(source);
         }
@@ -55,9 +54,7 @@ namespace System.Linq
             {
                 while (true)
                 {
-                    var t = e.MoveNext(CancellationToken.None);
-                    t.Wait();
-                    if (!t.Result)
+                    if (!e.MoveNext(CancellationToken.None).Result)
                         break;
                     var c = e.Current;
                     yield return c;
@@ -68,42 +65,32 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this Task<TSource> task)
         {
             if (task == null)
-                throw new ArgumentNullException("task");
-
+                throw new ArgumentNullException(nameof(task));
+            
             return Create(() =>
             {
                 var called = 0;
 
+                var value = default(TSource);
                 return Create(
-                    (ct, tcs) =>
+                    async ct =>
                     {
                         if (Interlocked.CompareExchange(ref called, 1, 0) == 0)
                         {
-                            task.Then(continuedTask =>
-                            {
-                                if (continuedTask.IsCanceled)
-                                    tcs.SetCanceled();
-                                else if (continuedTask.IsFaulted)
-                                    tcs.SetException(continuedTask.Exception.InnerException);
-                                else
-                                    tcs.SetResult(true);
-                            });
+                            value = await task.ConfigureAwait(false);
+                            return true;
                         }
-                        else
-                            tcs.SetResult(false);
-
-                        return tcs.Task;
+                        return false;
                     },
-                    () => task.Result,
+                    () => value,
                     () => { });
             });
         }
 
-#if !NO_RXINTERFACES
         public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IObservable<TSource> source)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
 
             return Create(() =>
             {
@@ -253,7 +240,7 @@ namespace System.Linq
         public static IObservable<TSource> ToObservable<TSource>(this IAsyncEnumerable<TSource> source)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
 
             return new ToObservableObservable<TSource>(source);
         }
@@ -304,6 +291,5 @@ namespace System.Linq
                 return Disposable.Create(ctd, e);
             }
         }
-#endif
     }
 }

+ 64 - 46
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Creation.cs

@@ -11,14 +11,14 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
-        static IAsyncEnumerable<T> Create<T>(Func<IAsyncEnumerator<T>> getEnumerator)
+        private static IAsyncEnumerable<T> Create<T>(Func<IAsyncEnumerator<T>> getEnumerator)
         {
             return new AnonymousAsyncEnumerable<T>(getEnumerator);
         }
 
-        class AnonymousAsyncEnumerable<T> : IAsyncEnumerable<T>
+        private class AnonymousAsyncEnumerable<T> : IAsyncEnumerable<T>
         {
-            Func<IAsyncEnumerator<T>> getEnumerator;
+            private Func<IAsyncEnumerator<T>> getEnumerator;
 
             public AnonymousAsyncEnumerable(Func<IAsyncEnumerator<T>> getEnumerator)
             {
@@ -31,16 +31,41 @@ namespace System.Linq
             }
         }
 
-        static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
+        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current,
+            Action dispose, IDisposable enumerator)
+        {
+            return Create(async ct =>
+            {
+                using (ct.Register(dispose))
+                {
+                    try
+                    {
+                        var result = await moveNext(ct).ConfigureAwait(false);
+                        if (!result)
+                        {
+                            enumerator?.Dispose();
+                        }
+                        return result;
+                    }
+                    catch
+                    {
+                        enumerator?.Dispose();
+                        throw;
+                    }
+                }
+            }, current, dispose);
+        }
+
+        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
         {
             return new AnonymousAsyncEnumerator<T>(moveNext, current, dispose);
         }
 
-        static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Action dispose)
+        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Action dispose)
         {
             var self = default(IAsyncEnumerator<T>);
             self = new AnonymousAsyncEnumerator<T>(
-                ct =>
+                async ct =>
                 {
                     var tcs = new TaskCompletionSource<bool>();
 
@@ -50,10 +75,10 @@ namespace System.Linq
                         tcs.TrySetCanceled();
                     });
 
-                    var ctr = ct.Register(stop);
-
-                    var res = moveNext(ct, tcs).Finally(ctr.Dispose);
-                    return res;
+                    using (ct.Register(stop))
+                    {
+                        return await moveNext(ct, tcs);
+                    }
                 },
                 current,
                 dispose
@@ -61,7 +86,7 @@ namespace System.Linq
             return self;
         }
 
-        class AnonymousAsyncEnumerator<T> : IAsyncEnumerator<T>
+        private class AnonymousAsyncEnumerator<T> : IAsyncEnumerator<T>
         {
             private readonly Func<CancellationToken, Task<bool>> _moveNext;
             private readonly Func<T> _current;
@@ -109,7 +134,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TValue> Throw<TValue>(Exception exception)
         {
             if (exception == null)
-                throw new ArgumentNullException("exception");
+                throw new ArgumentNullException(nameof(exception));
 
             return Create(() => Create<TValue>(
                 ct => TaskExt.Throw<bool>(exception),
@@ -139,7 +164,7 @@ namespace System.Linq
         public static IAsyncEnumerable<int> Range(int start, int count)
         {
             if (count < 0)
-                throw new ArgumentOutOfRangeException("count");
+                throw new ArgumentOutOfRangeException(nameof(count));
 
             return Enumerable.Range(start, count).ToAsyncEnumerable();
         }
@@ -147,7 +172,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TResult> Repeat<TResult>(TResult element, int count)
         {
             if (count < 0)
-                throw new ArgumentOutOfRangeException("count");
+                throw new ArgumentOutOfRangeException(nameof(count));
 
             return Enumerable.Repeat(element, count).ToAsyncEnumerable();
         }
@@ -167,7 +192,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Defer<TSource>(Func<IAsyncEnumerable<TSource>> factory)
         {
             if (factory == null)
-                throw new ArgumentNullException("factory");
+                throw new ArgumentNullException(nameof(factory));
 
             return Create(() => factory().GetEnumerator());
         }
@@ -175,11 +200,11 @@ namespace System.Linq
         public static IAsyncEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
         {
             if (condition == null)
-                throw new ArgumentNullException("condition");
+                throw new ArgumentNullException(nameof(condition));
             if (iterate == null)
-                throw new ArgumentNullException("iterate");
+                throw new ArgumentNullException(nameof(iterate));
             if (resultSelector == null)
-                throw new ArgumentNullException("resultSelector");
+                throw new ArgumentNullException(nameof(resultSelector));
 
             return Create(() =>
             {
@@ -223,9 +248,9 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IAsyncEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
         {
             if (resourceFactory == null)
-                throw new ArgumentNullException("resourceFactory");
+                throw new ArgumentNullException(nameof(resourceFactory));
             if (enumerableFactory == null)
-                throw new ArgumentNullException("enumerableFactory");
+                throw new ArgumentNullException(nameof(enumerableFactory));
 
             return Create(() =>
             {
@@ -248,36 +273,29 @@ namespace System.Linq
                 var current = default(TSource);
 
                 return Create(
-                    (ct, tcs) =>
+                    async ct =>
                     {
-                        e.MoveNext(cts.Token).Then(t =>
+                        bool res;
+                        try
                         {
-                            t.Handle(tcs,
-                                res =>
-                                {
-                                    if (res)
-                                    {
-                                        current = e.Current;
-                                        tcs.TrySetResult(true);
-                                    }
-                                    else
-                                    {
-                                        d.Dispose();
-                                        tcs.TrySetResult(false);
-                                    }
-                                },
-                                ex =>
-                                {
-                                    d.Dispose();
-                                    tcs.TrySetException(ex);
-                                }
-                            );
-                        });
-
-                        return tcs.Task;
+                            res = await e.MoveNext(cts.Token).ConfigureAwait(false);
+                        }
+                        catch (Exception)
+                        {
+                            d.Dispose();
+                            throw;
+                        }
+                        if (res)
+                        {
+                            current = e.Current;
+                            return true;
+                        }
+                        d.Dispose();
+                        return false;
                     },
                     () => current,
-                    d.Dispose
+                    d.Dispose,
+                    null
                 );
             });
         }

+ 80 - 184
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Exceptions.cs

@@ -4,6 +4,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.ExceptionServices;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -15,9 +16,9 @@ namespace System.Linq
             where TException : Exception
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
             if (handler == null)
-                throw new ArgumentNullException("handler");
+                throw new ArgumentNullException(nameof(handler));
 
             return Create(() =>
             {
@@ -28,74 +29,32 @@ namespace System.Linq
                 var d = Disposable.Create(cts, a);
                 var done = false;
 
-                var f = default(Action<TaskCompletionSource<bool>, CancellationToken>);
-                f = (tcs, ct) =>
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
                 {
                     if (!done)
                     {
-                        e.MoveNext(ct).Then(t =>
+                        try
                         {
-                            t.Handle(tcs,
-                                res =>
-                                {
-                                    tcs.TrySetResult(res);
-                                },
-                                ex =>
-                                {
-                                    var err = default(IAsyncEnumerator<TSource>);
-
-                                    try
-                                    {
-                                        ex.Flatten().Handle(ex_ =>
-                                        {
-                                            var exx = ex_ as TException;
-                                            if (exx != null)
-                                            {
-                                                err = handler(exx).GetEnumerator();
-                                                return true;
-                                            }
-
-                                            return false;
-                                        });
-                                    }
-                                    catch (Exception ex2)
-                                    {
-                                        tcs.TrySetException(ex2);
-                                        return;
-                                    }
-
-                                    if (err != null)
-                                    {
-                                        e = err;
-                                        a.Disposable = e;
-
-                                        done = true;
-                                        f(tcs, ct);
-                                    }
-                                }
-                            );
-                        });
-                    }
-                    else
-                    {
-                        e.MoveNext(ct).Then(t =>
+                            return await e.MoveNext(ct).ConfigureAwait(false);
+                        }
+                        catch (TException ex)
                         {
-                            t.Handle(tcs, res =>
-                            {
-                                tcs.TrySetResult(res);
-                            });
-                        });
+                            var err = handler(ex).GetEnumerator();
+                            e = err;
+                            a.Disposable = e;
+                            done = true;
+                            return await f(ct).ConfigureAwait(false);
+                        }
                     }
+                    return await e.MoveNext(ct).ConfigureAwait(false);
                 };
 
                 return Create(
-                    (ct, tcs) =>
-                    {
-                        f(tcs, cts.Token);
-                        return tcs.Task.UsingEnumerator(a);
-                    },
+                    f,
                     () => e.Current,
-                    d.Dispose
+                    d.Dispose,
+                    a
                 );
             });
         }
@@ -103,7 +62,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Catch<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
         {
             if (sources == null)
-                throw new ArgumentNullException("sources");
+                throw new ArgumentNullException(nameof(sources));
 
             return sources.Catch_();
         }
@@ -111,7 +70,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Catch<TSource>(params IAsyncEnumerable<TSource>[] sources)
         {
             if (sources == null)
-                throw new ArgumentNullException("sources");
+                throw new ArgumentNullException(nameof(sources));
 
             return sources.Catch_();
         }
@@ -119,9 +78,9 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Catch<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
         {
             if (first == null)
-                throw new ArgumentNullException("first");
+                throw new ArgumentNullException(nameof(first));
             if (second == null)
-                throw new ArgumentNullException("second");
+                throw new ArgumentNullException(nameof(second));
 
             return new[] { first, second }.Catch_();
         }
@@ -137,36 +96,21 @@ namespace System.Linq
                 var a = new AssignableDisposable();
                 var d = Disposable.Create(cts, se, a);
 
-                var error = default(Exception);
+                var error = default(ExceptionDispatchInfo);
 
-                var f = default(Action<TaskCompletionSource<bool>, CancellationToken>);
-                f = (tcs, ct) =>
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
                 {
                     if (e == null)
                     {
-                        var b = false;
-                        try
+                        if (se.MoveNext())
                         {
-                            b = se.MoveNext();
-                            if (b)
-                                e = se.Current.GetEnumerator();
+                            e = se.Current.GetEnumerator();
                         }
-                        catch (Exception ex)
+                        else
                         {
-                            tcs.TrySetException(ex);
-                            return;
-                        }
-
-                        if (!b)
-                        {
-                            if (error != null)
-                            {
-                                tcs.TrySetException(error);
-                                return;
-                            }
-
-                            tcs.TrySetResult(false);
-                            return;
+                            error?.Throw();
+                            return false;
                         }
 
                         error = null;
@@ -174,33 +118,24 @@ namespace System.Linq
                         a.Disposable = e;
                     }
 
-                    e.MoveNext(ct).Then(t =>
+                    try
+                    {
+                        return await e.MoveNext(ct).ConfigureAwait(false);
+                    }
+                    catch (Exception exception)
                     {
-                        t.Handle(tcs,
-                            res =>
-                            {
-                                tcs.TrySetResult(res);
-                            },
-                            ex =>
-                            {
-                                e.Dispose();
-                                e = null;
-
-                                error = ex;
-                                f(tcs, ct);
-                            }
-                        );
-                    });
+                        e.Dispose();
+                        e = null;
+                        error = ExceptionDispatchInfo.Capture(exception);
+                        return await f(ct).ConfigureAwait(false);
+                    }
                 };
 
                 return Create(
-                    (ct, tcs) =>
-                    {
-                        f(tcs, cts.Token);
-                        return tcs.Task.UsingEnumerator(a);
-                    },
+                    f,
                     () => e.Current,
-                    d.Dispose
+                    d.Dispose,
+                    a
                 );
             });
         }
@@ -208,9 +143,9 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Finally<TSource>(this IAsyncEnumerable<TSource> source, Action finallyAction)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
             if (finallyAction == null)
-                throw new ArgumentNullException("finallyAction");
+                throw new ArgumentNullException(nameof(finallyAction));
 
             return Create(() =>
             {
@@ -220,26 +155,11 @@ namespace System.Linq
                 var r = new Disposable(finallyAction);
                 var d = Disposable.Create(cts, e, r);
 
-                var f = default(Action<TaskCompletionSource<bool>, CancellationToken>);
-                f = (tcs, ct) =>
-                {
-                    e.MoveNext(ct).Then(t =>
-                    {
-                        t.Handle(tcs, res =>
-                        {
-                            tcs.TrySetResult(res);
-                        });
-                    });
-                };
-
                 return Create(
-                    (ct, tcs) =>
-                    {
-                        f(tcs, cts.Token);
-                        return tcs.Task.UsingEnumerator(r);
-                    },
+                    ct => e.MoveNext(ct),
                     () => e.Current,
-                    d.Dispose
+                    d.Dispose,
+                    r
                 );
             });
         }
@@ -247,9 +167,9 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
         {
             if (first == null)
-                throw new ArgumentNullException("first");
+                throw new ArgumentNullException(nameof(first));
             if (second == null)
-                throw new ArgumentNullException("second");
+                throw new ArgumentNullException(nameof(second));
 
             return OnErrorResumeNext_(new[] { first, second });
         }
@@ -257,7 +177,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(params IAsyncEnumerable<TSource>[] sources)
         {
             if (sources == null)
-                throw new ArgumentNullException("sources");
+                throw new ArgumentNullException(nameof(sources));
 
             return OnErrorResumeNext_(sources);
         }
@@ -265,7 +185,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
         {
             if (sources == null)
-                throw new ArgumentNullException("sources");
+                throw new ArgumentNullException(nameof(sources));
 
             return OnErrorResumeNext_(sources);
         }
@@ -281,69 +201,45 @@ namespace System.Linq
                 var a = new AssignableDisposable();
                 var d = Disposable.Create(cts, se, a);
 
-                var f = default(Action<TaskCompletionSource<bool>, CancellationToken>);
-                f = (tcs, ct) =>
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
                 {
                     if (e == null)
                     {
                         var b = false;
-                        try
+                        b = se.MoveNext();
+                        if (b)
+                            e = se.Current.GetEnumerator();
+                        else
                         {
-                            b = se.MoveNext();
-                            if (b)
-                                e = se.Current.GetEnumerator();
-                        }
-                        catch (Exception ex)
-                        {
-                            tcs.TrySetException(ex);
-                            return;
-                        }
-
-                        if (!b)
-                        {
-                            tcs.TrySetResult(false);
-                            return;
+                            return false;
                         }
 
                         a.Disposable = e;
                     }
 
-                    e.MoveNext(ct).Then(t =>
+                    try
+                    {
+                        if (await e.MoveNext(ct).ConfigureAwait(false))
+                        {
+                            return true;
+                        }
+                    }
+                    catch
                     {
-                        t.Handle(tcs,
-                            res =>
-                            {
-                                if (res)
-                                {
-                                    tcs.TrySetResult(true);
-                                }
-                                else
-                                {
-                                    e.Dispose();
-                                    e = null;
-
-                                    f(tcs, ct);
-                                }
-                            },
-                            ex =>
-                            {
-                                e.Dispose();
-                                e = null;
-
-                                f(tcs, ct);
-                            }
-                        );
-                    });
+                        // ignore
+                    }
+
+                    e.Dispose();
+                    e = null;
+                    return await f(ct).ConfigureAwait(false);
                 };
 
                 return Create(
-                    (ct, tcs) =>
-                    {
-                        f(tcs, cts.Token);
-                        return tcs.Task.UsingEnumerator(a);
-                    },
+                    f,
                     () => e.Current,
-                    d.Dispose
+                    d.Dispose,
+                    a
                 );
             });
         }
@@ -351,7 +247,7 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
 
             return new[] { source }.Repeat().Catch();
         }
@@ -359,9 +255,9 @@ namespace System.Linq
         public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source, int retryCount)
         {
             if (source == null)
-                throw new ArgumentNullException("source");
+                throw new ArgumentNullException(nameof(source));
             if (retryCount < 0)
-                throw new ArgumentOutOfRangeException("retryCount");
+                throw new ArgumentOutOfRangeException(nameof(retryCount));
 
             return new[] { source }.Repeat(retryCount).Catch();
         }

Diferenças do arquivo suprimidas por serem muito extensas
+ 322 - 431
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Multiple.cs


Diferenças do arquivo suprimidas por serem muito extensas
+ 201 - 470
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Single.cs


+ 1 - 1
Ix.NET/Source/System.Interactive.Async/AsyncEnumerator.cs

@@ -20,7 +20,7 @@ namespace System.Collections.Generic
         public static Task<bool> MoveNext<T>(this IAsyncEnumerator<T> enumerator)
         {
             if (enumerator == null)
-                throw new ArgumentNullException("enumerator");
+                throw new ArgumentNullException(nameof(enumerator));
 
             return enumerator.MoveNext(CancellationToken.None);
         }

+ 17 - 0
Ix.NET/Source/System.Interactive.Async/EmptyArray.cs

@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+#if NO_ARRAY_EMPTY
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    internal sealed class EmptyArray<TElement>
+    {
+        public static readonly TElement[] Value = new TElement[0];
+    }
+}
+#endif

+ 131 - 0
Ix.NET/Source/System.Interactive.Async/Grouping.cs

@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq.Internal
+{
+    /// Adapted from System.Linq.Grouping from .NET Framework
+    /// Source: https://github.com/dotnet/corefx/blob/b90532bc97b07234a7d18073819d019645285f1c/src/System.Linq/src/System/Linq/Grouping.cs#L64
+    internal class Grouping<TKey, TElement> : IGrouping<TKey, TElement>, IList<TElement>
+    {
+        internal TKey _key;
+        internal int _hashCode;
+        internal TElement[] _elements;
+        internal int _count;
+        internal Grouping<TKey, TElement> _hashNext;
+        internal Grouping<TKey, TElement> _next;
+
+        internal Grouping()
+        {
+        }
+
+        internal void Add(TElement element)
+        {
+            if (_elements.Length == _count)
+            {
+                Array.Resize(ref _elements, checked(_count * 2));
+            }
+
+            _elements[_count] = element;
+            _count++;
+        }
+
+        internal void Trim()
+        {
+            if (_elements.Length != _count)
+            {
+                Array.Resize(ref _elements, _count);
+            }
+        }
+
+        public IEnumerator<TElement> GetEnumerator()
+        {
+            for (int i = 0; i < _count; i++)
+            {
+                yield return _elements[i];
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        // DDB195907: implement IGrouping<>.Key implicitly
+        // so that WPF binding works on this property.
+        public TKey Key
+        {
+            get { return _key; }
+        }
+
+        int ICollection<TElement>.Count
+        {
+            get { return _count; }
+        }
+
+        bool ICollection<TElement>.IsReadOnly
+        {
+            get { return true; }
+        }
+
+        void ICollection<TElement>.Add(TElement item)
+        {
+            throw new NotSupportedException(Strings.NOT_SUPPORTED);
+        }
+
+        void ICollection<TElement>.Clear()
+        {
+            throw new NotSupportedException(Strings.NOT_SUPPORTED);
+        }
+
+        bool ICollection<TElement>.Contains(TElement item)
+        {
+            return Array.IndexOf(_elements, item, 0, _count) >= 0;
+        }
+
+        void ICollection<TElement>.CopyTo(TElement[] array, int arrayIndex)
+        {
+            Array.Copy(_elements, 0, array, arrayIndex, _count);
+        }
+
+        bool ICollection<TElement>.Remove(TElement item)
+        {
+            throw new NotSupportedException(Strings.NOT_SUPPORTED);
+        }
+
+        int IList<TElement>.IndexOf(TElement item)
+        {
+            return Array.IndexOf(_elements, item, 0, _count);
+        }
+
+        void IList<TElement>.Insert(int index, TElement item)
+        {
+            throw new NotSupportedException(Strings.NOT_SUPPORTED);
+        }
+
+        void IList<TElement>.RemoveAt(int index)
+        {
+            throw new NotSupportedException(Strings.NOT_SUPPORTED);
+        }
+
+        TElement IList<TElement>.this[int index]
+        {
+            get
+            {
+                if (index < 0 || index >= _count)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(index));
+                }
+
+                return _elements[index];
+            }
+
+            set
+            {
+                throw new NotSupportedException(Strings.NOT_SUPPORTED);
+            }
+        }
+    }
+}

+ 275 - 0
Ix.NET/Source/System.Interactive.Async/Lookup.cs

@@ -0,0 +1,275 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq.Internal
+{
+    internal class Lookup<TKey, TElement> : ILookup<TKey, TElement>
+    {
+        private readonly IEqualityComparer<TKey> _comparer;
+        private Grouping<TKey, TElement>[] _groupings;
+        private Grouping<TKey, TElement> _lastGrouping;
+        private int _count;
+
+        internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+        {
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
+            Debug.Assert(elementSelector != null);
+
+            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (TSource item in source)
+            {
+                lookup.GetGrouping(keySelector(item), create: true).Add(elementSelector(item));
+            }
+
+            return lookup;
+        }
+
+        internal static async Task<Lookup<TKey, TElement>> CreateAsync<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
+            Debug.Assert(elementSelector != null);
+
+            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
+            using (var enu = source.GetEnumerator())
+            {
+                while (await enu.MoveNext(cancellationToken)
+                                .ConfigureAwait(false))
+                {
+                    lookup.GetGrouping(keySelector(enu.Current), create: true).Add(elementSelector(enu.Current));
+                }
+            }
+
+            return lookup;
+        }
+
+        internal static Lookup<TKey, TElement> Create(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
+
+            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (TElement item in source)
+            {
+                lookup.GetGrouping(keySelector(item), create: true).Add(item);
+            }
+
+            return lookup;
+        }
+
+        internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (TElement item in source)
+            {
+                TKey key = keySelector(item);
+                if (key != null)
+                {
+                    lookup.GetGrouping(key, create: true).Add(item);
+                }
+            }
+
+            return lookup;
+        }
+
+        internal static async Task<Lookup<TKey, TElement>> CreateForJoinAsync(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
+            using (var enu = source.GetEnumerator())
+            {
+                while (await enu.MoveNext(cancellationToken)
+                                .ConfigureAwait(false))
+                {
+                    TKey key = keySelector(enu.Current);
+                    if (key != null)
+                    {
+                        lookup.GetGrouping(key, create: true).Add(enu.Current);
+                    }
+                }
+            }
+
+            return lookup;
+        }
+
+        private Lookup(IEqualityComparer<TKey> comparer)
+        {
+            _comparer = comparer ?? EqualityComparer<TKey>.Default;
+            _groupings = new Grouping<TKey, TElement>[7];
+        }
+
+        public int Count
+        {
+            get { return _count; }
+        }
+
+        public IEnumerable<TElement> this[TKey key]
+        {
+            get
+            {
+                Grouping<TKey, TElement> grouping = GetGrouping(key, create: false);
+                if (grouping != null)
+                {
+                    return grouping;
+                }
+
+#if NO_ARRAY_EMPTY
+                return EmptyArray<TElement>.Value;
+#else
+                return Array.Empty<TElement>();
+#endif
+            }
+        }
+
+        public bool Contains(TKey key)
+        {
+            return GetGrouping(key, create: false) != null;
+        }
+
+        public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
+        {
+            Grouping<TKey, TElement> g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    yield return g;
+                }
+                while (g != _lastGrouping);
+            }
+        }
+
+        internal TResult[] ToArray<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        {
+            TResult[] array = new TResult[_count];
+            int index = 0;
+            Grouping<TKey, TElement> g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    g.Trim();
+                    array[index] = resultSelector(g._key, g._elements);
+                    ++index;
+                }
+                while (g != _lastGrouping);
+            }
+
+            return array;
+        }
+
+
+        internal List<TResult> ToList<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        {
+            List<TResult> list = new List<TResult>(_count);
+            Grouping<TKey, TElement> g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    g.Trim();
+                    list.Add(resultSelector(g._key, g._elements));
+                }
+                while (g != _lastGrouping);
+            }
+
+            return list;
+        }
+
+        public IEnumerable<TResult> ApplyResultSelector<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        {
+            Grouping<TKey, TElement> g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    g.Trim();
+                    yield return resultSelector(g._key, g._elements);
+                }
+                while (g != _lastGrouping);
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        internal int InternalGetHashCode(TKey key)
+        {
+            // Handle comparer implementations that throw when passed null
+            return (key == null) ? 0 : _comparer.GetHashCode(key) & 0x7FFFFFFF;
+        }
+
+        internal Grouping<TKey, TElement> GetGrouping(TKey key, bool create)
+        {
+            int hashCode = InternalGetHashCode(key);
+            for (Grouping<TKey, TElement> g = _groupings[hashCode % _groupings.Length]; g != null; g = g._hashNext)
+            {
+                if (g._hashCode == hashCode && _comparer.Equals(g._key, key))
+                {
+                    return g;
+                }
+            }
+
+            if (create)
+            {
+                if (_count == _groupings.Length)
+                {
+                    Resize();
+                }
+
+                int index = hashCode % _groupings.Length;
+                Grouping<TKey, TElement> g = new Grouping<TKey, TElement>();
+                g._key = key;
+                g._hashCode = hashCode;
+                g._elements = new TElement[1];
+                g._hashNext = _groupings[index];
+                _groupings[index] = g;
+                if (_lastGrouping == null)
+                {
+                    g._next = g;
+                }
+                else
+                {
+                    g._next = _lastGrouping._next;
+                    _lastGrouping._next = g;
+                }
+
+                _lastGrouping = g;
+                _count++;
+                return g;
+            }
+
+            return null;
+        }
+
+        private void Resize()
+        {
+            int newSize = checked((_count * 2) + 1);
+            Grouping<TKey, TElement>[] newGroupings = new Grouping<TKey, TElement>[newSize];
+            Grouping<TKey, TElement> g = _lastGrouping;
+            do
+            {
+                g = g._next;
+                int index = g._hashCode % newSize;
+                g._hashNext = newGroupings[index];
+                newGroupings[index] = g;
+            }
+            while (g != _lastGrouping);
+
+            _groupings = newGroupings;
+        }
+    }
+
+}

+ 1 - 0
Ix.NET/Source/System.Interactive.Async/Strings.cs

@@ -7,5 +7,6 @@ namespace System.Linq
     {
         public static string NO_ELEMENTS = "Source sequence doesn't contain any elements.";
         public static string MORE_THAN_ONE_ELEMENT = "Source sequence contains more than one element.";
+        public static string NOT_SUPPORTED = "Specified method is not supported.";
     }
 }

+ 3 - 108
Ix.NET/Source/System.Interactive.Async/TaskExt.cs

@@ -1,30 +1,15 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
-using System;
 using System.Collections.Generic;
-using System.Linq;
 
 namespace System.Threading.Tasks
 {
     static class TaskExt
     {
-        public static readonly Task<bool> True;
-        public static readonly Task<bool> False;
-
-        static TaskExt()
-        {
-            True = Return(true);
-            False = Return(false);
-        }
-
-        public static Task<T> Return<T>(T value)
-        {
-            var tcs = new TaskCompletionSource<T>();
-            tcs.TrySetResult(value);
-            return tcs.Task;
-        }
-
+        public static readonly Task<bool> True = Task.FromResult(true);
+        public static readonly Task<bool> False = Task.FromResult(false);
+        
         public static Task<T> Throw<T>(Exception exception)
         {
             var tcs = new TaskCompletionSource<T>();
@@ -32,98 +17,8 @@ namespace System.Threading.Tasks
             return tcs.Task;
         }
 
-        public static void Handle<T, R>(this Task<T> task, TaskCompletionSource<R> tcs, Action<T> success)
-        {
-            if (task.IsFaulted)
-                tcs.TrySetException(task.Exception.InnerExceptions);
-            else if (task.IsCanceled)
-                tcs.TrySetCanceled();
-            else if (task.IsCompleted)
-                success(task.Result);
-        }
-
-        public static void Handle<T, R>(this Task<T> task, TaskCompletionSource<R> tcs, Action<T> success, Action<AggregateException> error)
-        {
-            if (task.IsFaulted)
-                error(task.Exception);
-            else if (task.IsCanceled)
-                tcs.TrySetCanceled();
-            else if (task.IsCompleted)
-                success(task.Result);
-        }
-
-        public static void Handle<T, R>(this Task<T> task, TaskCompletionSource<R> tcs, Action<T> success, Action<AggregateException> error, Action canceled)
-        {
-            if (task.IsFaulted)
-                error(task.Exception);
-            else if (task.IsCanceled)
-                canceled();
-            else if (task.IsCompleted)
-                success(task.Result);
-        }
-
-        public static Task Then<T>(this Task<T> task, Action<Task<T>> continuation)
-        {
-            //
-            // Central location to deal with continuations; allows for experimentation with flags.
-            // Note that right now, we don't go for synchronous execution. Users can block on the
-            // task returned from MoveNext, which can cause deadlocks (e.g. typical uses of GroupBy
-            // involve some aggregate). We'd need deeper asynchrony to make this work with less
-            // spawning of tasks.
-            //
-            return task.ContinueWith(continuation);
-        }
-
-        public static Task<R> Then<T, R>(this Task<T> task, Func<Task<T>, R> continuation)
-        {
-            //
-            // See comment on Then<T> for rationale.
-            //
-            return task.ContinueWith(continuation);
-        }
-
-        public static Task<bool> UsingEnumerator(this Task<bool> task, IDisposable disposable)
-        {
-            return task.Finally(() =>
-            {
-                if (task.IsFaulted || task.IsCanceled || !task.Result)
-                    disposable.Dispose();
-            });
-        }
-
-        public static Task<R> Finally<R>(this Task<R> task, Action action)
-        {
-            var tcs = new TaskCompletionSource<R>();
-
-            task.ContinueWith(t =>
-            {
-                try
-                {
-                    action();
-                }
-                finally
-                {
-                    switch (t.Status)
-                    {
-                        case TaskStatus.Canceled:
-                            tcs.SetCanceled();
-                            break;
-                        case TaskStatus.Faulted:
-                            tcs.SetException(t.Exception.InnerException);
-                            break;
-                        case TaskStatus.RanToCompletion:
-                            tcs.SetResult(t.Result);
-                            break;
-                    }
-                }
-            }, TaskContinuationOptions.ExecuteSynchronously);
-
-            return tcs.Task;
-        }
-
         public static Task<V> Zip<T, U, V>(this Task<T> t1, Task<U> t2, Func<T, U, V> f)
         {
-            var gate = new object();
             var tcs = new TaskCompletionSource<V>();
 
             var i = 2;

+ 21 - 0
Ix.NET/Source/System.Interactive.Async/project.json

@@ -33,12 +33,33 @@
         "define": [
           "HAS_AWAIT",
           "HAS_APTCA",
+          "NO_ARRAY_EMPTY",
           "DESKTOPCLR",
           "DESKTOPCLR45"
         ]
       }
     },
+    "net46": {
+      "buildOptions": {
+        "define": [
+          "HAS_AWAIT",
+          "HAS_APTCA",
+          "DESKTOPCLR",
+          "DESKTOPCLR46"
+        ]
+      }
+    },
     "netstandard1.0": {
+      "buildOptions": {
+        "define": [
+          "HAS_AWAIT",
+          "NO_ARRAY_EMPTY",
+          "CRIPPLED_REFLECTION",
+          "PLIB"
+        ]
+      }
+    },
+    "netstandard1.3": {
       "buildOptions": {
         "define": [
           "HAS_AWAIT",

Diferenças do arquivo suprimidas por serem muito extensas
+ 282 - 277
Ix.NET/Source/Tests/AsyncTests.Aggregates.cs


+ 2 - 2
Ix.NET/Source/Tests/AsyncTests.Bugs.cs

@@ -157,7 +157,7 @@ namespace Tests
 
             try
             {
-                t.Wait();
+                t.Wait(WaitTimeoutMs);
             }
             catch
             {
@@ -191,7 +191,7 @@ namespace Tests
 
             try
             {
-                t.Wait();
+                t.Wait(WaitTimeoutMs);
                 Assert.True(false);
             }
             catch

+ 4 - 4
Ix.NET/Source/Tests/AsyncTests.Conversions.cs

@@ -40,7 +40,7 @@ namespace Tests
             var xs = ToAsyncEnumerable_Sequence(ex).ToAsyncEnumerable();
             var e = xs.GetEnumerator();
             HasNext(e, 42);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         private IEnumerable<int> ToAsyncEnumerable_Sequence(Exception e)
@@ -95,7 +95,7 @@ namespace Tests
 
             Assert.True(subscribed);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -121,7 +121,7 @@ namespace Tests
             var xs = tcs.Task.ToAsyncEnumerable();
             var e = xs.GetEnumerator();
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -133,7 +133,7 @@ namespace Tests
             var xs = tcs.Task.ToAsyncEnumerable();
             var e = xs.GetEnumerator();
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() is TaskCanceledException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() is TaskCanceledException);
         }
 
         class MyObservable<T> : IObservable<T>

+ 6 - 6
Ix.NET/Source/Tests/AsyncTests.Creation.cs

@@ -71,7 +71,7 @@ namespace Tests
             var xs = AsyncEnumerable.Throw<int>(ex);
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
             AssertThrows<InvalidOperationException>(() => Nop(e.Current));
         }
 
@@ -207,7 +207,7 @@ namespace Tests
             var xs = AsyncEnumerable.Generate(0, x => { throw ex; }, x => x + 1, x => x * x);
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -218,7 +218,7 @@ namespace Tests
 
             var e = xs.GetEnumerator();
             HasNext(e, 0);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -229,7 +229,7 @@ namespace Tests
 
             var e = xs.GetEnumerator();
             HasNext(e, 0);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -354,7 +354,7 @@ namespace Tests
             var e = xs.GetEnumerator();
             Assert.Equal(1, i);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
 
             Assert.True(disposed.Task.Result);
         }
@@ -388,7 +388,7 @@ namespace Tests
 
             try
             {
-                t.Wait();
+                t.Wait(WaitTimeoutMs);
             }
             catch (AggregateException ex)
             {

+ 8 - 8
Ix.NET/Source/Tests/AsyncTests.Exceptions.cs

@@ -114,7 +114,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
 
             Assert.False(err);
         }
@@ -135,7 +135,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex2);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex2);
         }
 
         [Fact]
@@ -162,7 +162,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -233,7 +233,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
         }
 
         private IEnumerable<IAsyncEnumerable<int>> CatchXss()
@@ -259,7 +259,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -323,7 +323,7 @@ namespace Tests
             var e = xs.GetEnumerator();
 
             Assert.False(b);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
 
             Assert.True(b);
         }
@@ -379,7 +379,7 @@ namespace Tests
 
             var t = e.MoveNext(cts.Token);
             cts.Cancel();
-            t.Wait();
+            t.Wait(WaitTimeoutMs);
 
             Assert.True(b);
         }
@@ -467,7 +467,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 3);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
         }
 
         private IEnumerable<IAsyncEnumerable<int>> OnErrorResumeNextXss()

+ 34 - 33
Ix.NET/Source/Tests/AsyncTests.Multiple.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using Xunit;
 using System.Threading;
+using System.Threading.Tasks;
 
 namespace Tests
 {
@@ -48,7 +49,7 @@ namespace Tests
             HasNext(e, 1);
             HasNext(e, 2);
             HasNext(e, 3);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -58,7 +59,7 @@ namespace Tests
             var ys = AsyncEnumerable.Throw<int>(ex).Concat(new[] { 4, 5, 6 }.ToAsyncEnumerable());
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -98,7 +99,7 @@ namespace Tests
             HasNext(e, 3);
             HasNext(e, 4);
             HasNext(e, 5);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -112,7 +113,7 @@ namespace Tests
             HasNext(e, 3);
             HasNext(e, 4);
             HasNext(e, 5);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
         }
 
         static IEnumerable<IAsyncEnumerable<int>> ConcatXss()
@@ -181,7 +182,7 @@ namespace Tests
             var res = xs.Zip(ys, (x, y) => x * y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -193,7 +194,7 @@ namespace Tests
             var res = xs.Zip(ys, (x, y) => x * y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -205,7 +206,7 @@ namespace Tests
             var res = xs.Zip(ys, (x, y) => { if (x > 0) throw ex; return x * y; });
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -324,21 +325,21 @@ namespace Tests
         }
 
         [Fact]
-        public void SequenceEqual_Null()
+        public async Task SequenceEqual_Null()
         {
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42)));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42)));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null));
 
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), new Eq()));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, new Eq()));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), AsyncEnumerable.Return(42), null));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), new Eq()));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, new Eq()));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), AsyncEnumerable.Return(42), null));
 
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, CancellationToken.None));
 
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), new Eq(), CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, new Eq(), CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), AsyncEnumerable.Return(42), null, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(null, AsyncEnumerable.Return(42), new Eq(), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), null, new Eq(), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SequenceEqual<int>(AsyncEnumerable.Return(42), AsyncEnumerable.Return(42), null, CancellationToken.None));
         }
 
         [Fact]
@@ -392,7 +393,7 @@ namespace Tests
             var ys = AsyncEnumerable.Throw<int>(ex);
             var res = xs.SequenceEqual(ys);
 
-            AssertThrows<Exception>(() => res.Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -403,7 +404,7 @@ namespace Tests
             var ys = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
             var res = xs.SequenceEqual(ys);
 
-            AssertThrows<Exception>(() => res.Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -457,7 +458,7 @@ namespace Tests
             var ys = AsyncEnumerable.Throw<int>(ex);
             var res = xs.SequenceEqual(ys, new Eq());
 
-            AssertThrows<Exception>(() => res.Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -468,7 +469,7 @@ namespace Tests
             var ys = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
             var res = xs.SequenceEqual(ys, new Eq());
 
-            AssertThrows<Exception>(() => res.Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -486,7 +487,7 @@ namespace Tests
             var xs = new[] { 1, 2, -3, 4 }.ToAsyncEnumerable();
             var ys = new[] { 1, -2, 3, 4 }.ToAsyncEnumerable();
             var res = xs.SequenceEqual(ys, new EqEx());
-            AssertThrows<Exception>(() => res.Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
+            AssertThrows<Exception>(() => res.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
         }
 
         class EqEx : IEqualityComparer<int>
@@ -559,7 +560,7 @@ namespace Tests
             var res = xs.GroupJoin(ys, x => x % 3, y => y % 3, (x, i) => x + " - " + i.Aggregate("", (s, j) => s + j).Result);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -572,7 +573,7 @@ namespace Tests
             var res = xs.GroupJoin(ys, x => x % 3, y => y % 3, (x, i) => x + " - " + i.Aggregate("", (s, j) => s + j).Result);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -585,7 +586,7 @@ namespace Tests
             var res = xs.GroupJoin(ys, x => { throw ex; }, y => y % 3, (x, i) => x + " - " + i.Aggregate("", (s, j) => s + j).Result);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -598,7 +599,7 @@ namespace Tests
             var res = xs.GroupJoin(ys, x => x % 3, y => { throw ex; }, (x, i) => x + " - " + i.Aggregate("", (s, j) => s + j).Result);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -616,7 +617,7 @@ namespace Tests
 
             var e = res.GetEnumerator();
             HasNext(e, "0 - 36");
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -704,7 +705,7 @@ namespace Tests
             var res = xs.Join(ys, x => x % 3, y => y % 3, (x, y) => x + y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -717,7 +718,7 @@ namespace Tests
             var res = xs.Join(ys, x => x % 3, y => y % 3, (x, y) => x + y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -730,7 +731,7 @@ namespace Tests
             var res = xs.Join(ys, x => { throw ex; }, y => y, (x, y) => x + y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -743,7 +744,7 @@ namespace Tests
             var res = xs.Join(ys, x => x, y => { throw ex; }, (x, y) => x + y);
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -756,7 +757,7 @@ namespace Tests
             var res = xs.Join<int, int, int, int>(ys, x => x, y => y, (x, y) => { throw ex; });
 
             var e = res.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]

+ 69 - 68
Ix.NET/Source/Tests/AsyncTests.Single.cs

@@ -9,6 +9,7 @@ using System.Linq;
 using System.Text;
 using Xunit;
 using System.Threading;
+using System.Threading.Tasks;
 
 namespace Tests
 {
@@ -56,7 +57,7 @@ namespace Tests
             var ys = xs.Select(x => 1 / x);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is DivideByZeroException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is DivideByZeroException);
         }
 
         [Fact]
@@ -66,7 +67,7 @@ namespace Tests
             var ys = xs.Select((x, i) => 1 / i);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is DivideByZeroException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is DivideByZeroException);
         }
 
         [Fact]
@@ -118,7 +119,7 @@ namespace Tests
             HasNext(e, 8);
             HasNext(e, 5);
             HasNext(e, 7);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -132,7 +133,7 @@ namespace Tests
             HasNext(e, 8);
             HasNext(e, 5);
             HasNext(e, 7);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -143,7 +144,7 @@ namespace Tests
             var ys = xs.Where(x => true);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -154,7 +155,7 @@ namespace Tests
 
             var ys = xs.Where((x, i) => true);
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -206,7 +207,7 @@ namespace Tests
             HasNext(e, 0);
             HasNext(e, 0);
             HasNext(e, 1);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -217,7 +218,7 @@ namespace Tests
             var ys = xs.SelectMany(x => Enumerable.Range(0, x).ToAsyncEnumerable());
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -237,7 +238,7 @@ namespace Tests
             HasNext(e, 0);
             HasNext(e, 0);
             HasNext(e, 1);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -273,7 +274,7 @@ namespace Tests
             HasNext(e, 0);
             HasNext(e, 0);
             HasNext(e, 1);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -284,7 +285,7 @@ namespace Tests
             var ys = xs.SelectMany((x, i) => Enumerable.Range(0, x).ToAsyncEnumerable());
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -304,7 +305,7 @@ namespace Tests
             HasNext(e, 0);
             HasNext(e, 0);
             HasNext(e, 1);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -356,7 +357,7 @@ namespace Tests
             HasNext(e, 6);
             HasNext(e, 8);
             HasNext(e, 9);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -375,7 +376,7 @@ namespace Tests
             HasNext(e, 3);
             HasNext(e, 8);
             HasNext(e, 10);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -484,7 +485,7 @@ namespace Tests
             var ys = xs.Do(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -544,11 +545,11 @@ namespace Tests
             var ys = xs.Do(x => { hasv = true; }, exx => { exa = exx; }, () => { done = true; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ex_.InnerException == ex);
 
             Assert.False(hasv);
             Assert.False(done);
-            Assert.Same(((AggregateException)exa).Flatten().InnerExceptions.Single(), ex);
+            Assert.Same(exa, ex);
         }
 
         [Fact]
@@ -561,24 +562,24 @@ namespace Tests
             var ys = xs.Do(x => { hasv = true; }, exx => { exa = exx; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ex_.InnerException == ex);
 
             Assert.False(hasv);
-            Assert.Same(((AggregateException)exa).Flatten().InnerExceptions.Single(), ex);
+            Assert.Same(exa, ex);
         }
 
         [Fact]
-        public void ForEachAsync_Null()
+        public async Task ForEachAsync_Null()
         {
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, x => { }));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int>)));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, (x, i) => { }));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int, int>)));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, x => { }));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int>)));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, (x, i) => { }));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int, int>)));
 
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, x => { }, CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int>), CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, (x, i) => { }, CancellationToken.None));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int, int>), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, x => { }, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int>), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(null, (x, i) => { }, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(AsyncEnumerable.Return(42), default(Action<int, int>), CancellationToken.None));
         }
 
         [Fact]
@@ -601,7 +602,7 @@ namespace Tests
             var sum = 0;
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
 
-            xs.ForEachAsync(x => sum += x).Wait();
+            xs.ForEachAsync(x => sum += x).Wait(WaitTimeoutMs);
             Assert.Equal(10, sum);
         }
 
@@ -631,7 +632,7 @@ namespace Tests
             var sum = 0;
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
 
-            xs.ForEachAsync((x, i) => sum += x * i).Wait();
+            xs.ForEachAsync((x, i) => sum += x * i).Wait(WaitTimeoutMs);
             Assert.Equal(1 * 0 + 2 * 1 + 3 * 2 + 4 * 3, sum);
         }
 
@@ -641,7 +642,7 @@ namespace Tests
             var ex = new Exception("Bang");
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
 
-            AssertThrows<Exception>(() => xs.ForEachAsync(x => { throw ex; }).Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => xs.ForEachAsync(x => { throw ex; }).Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -659,7 +660,7 @@ namespace Tests
             var ex = new Exception("Bang");
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
 
-            AssertThrows<Exception>(() => xs.ForEachAsync((x, i) => { throw ex; }).Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => xs.ForEachAsync((x, i) => { throw ex; }).Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -677,7 +678,7 @@ namespace Tests
             var ex = new Exception("Bang");
             var xs = AsyncEnumerable.Throw<int>(ex);
 
-            AssertThrows<Exception>(() => xs.ForEachAsync(x => { throw ex; }).Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => xs.ForEachAsync(x => { throw ex; }).Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -695,7 +696,7 @@ namespace Tests
             var ex = new Exception("Bang");
             var xs = AsyncEnumerable.Throw<int>(ex);
 
-            AssertThrows<Exception>(() => xs.ForEachAsync((x, i) => { throw ex; }).Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => xs.ForEachAsync((x, i) => { throw ex; }).Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -758,7 +759,7 @@ namespace Tests
             var ys = xs.Take(2);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -826,7 +827,7 @@ namespace Tests
             var ys = xs.TakeWhile(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -873,7 +874,7 @@ namespace Tests
             var ys = xs.TakeWhile((x, i) => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -927,7 +928,7 @@ namespace Tests
             var ys = xs.Skip(2);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -998,7 +999,7 @@ namespace Tests
             var ys = xs.SkipWhile(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1045,7 +1046,7 @@ namespace Tests
             var ys = xs.SkipWhile((x, i) => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1128,7 +1129,7 @@ namespace Tests
             var xs = AsyncEnumerable.Throw<int>(ex).DefaultIfEmpty();
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1138,7 +1139,7 @@ namespace Tests
             var xs = AsyncEnumerable.Throw<int>(ex).DefaultIfEmpty(24);
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1225,7 +1226,7 @@ namespace Tests
             var ys = xs.Reverse();
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1282,7 +1283,7 @@ namespace Tests
             var ys = xs.OrderBy<int, int>(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1293,7 +1294,7 @@ namespace Tests
             var ys = xs.OrderBy<int, int>(x => x).ThenBy<int, int>(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1316,7 +1317,7 @@ namespace Tests
             var ys = xs.OrderByDescending<int, int>(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1327,7 +1328,7 @@ namespace Tests
             var ys = xs.OrderBy<int, int>(x => x).ThenByDescending<int, int>(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1578,7 +1579,7 @@ namespace Tests
             var ys = xs.GroupBy(x => x);
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1601,9 +1602,9 @@ namespace Tests
             var g2e = g2.GetEnumerator();
             HasNext(g2e, 43);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-            AssertThrows<Exception>(() => g1e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-            AssertThrows<Exception>(() => g2e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
         }
 
         [Fact]
@@ -1619,9 +1620,9 @@ namespace Tests
             Assert.Equal(g1.Key, 42);
             var g1e = g1.GetEnumerator();
             HasNext(g1e, 42);
-            AssertThrows<Exception>(() => g1e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");           
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");           
         }
 
         static IEnumerable<int> GetXs()
@@ -1639,7 +1640,7 @@ namespace Tests
             var ys = xs.GroupBy<int, int>(x => { throw ex; });
 
             var e = ys.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1663,9 +1664,9 @@ namespace Tests
             var g2e = g2.GetEnumerator();
             HasNext(g2e, 2);
 
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-            AssertThrows<Exception>(() => g1e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-            AssertThrows<Exception>(() => g2e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -1941,7 +1942,7 @@ namespace Tests
         [Fact]
         public void AsAsyncEnumerable_Null()
         {
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.AsAsyncEnumerable<int>(null));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.AsAsyncEnumerable<int>((IAsyncEnumerable<int>)null));
         }
 
         [Fact]
@@ -2032,7 +2033,7 @@ namespace Tests
             var xs = new FailRepeat().ToAsyncEnumerable().Repeat();
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
         }
 
         [Fact]
@@ -2041,7 +2042,7 @@ namespace Tests
             var xs = new FailRepeat().ToAsyncEnumerable().Repeat(3);
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NotImplementedException);
         }
 
         class FailRepeat : IEnumerable<int>
@@ -2103,7 +2104,7 @@ namespace Tests
             var xs = AsyncEnumerable.Throw<int>(ex).IgnoreElements();
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2145,7 +2146,7 @@ namespace Tests
             var e = xs.GetEnumerator();
             HasNext(e, 1);
             HasNext(e, 2);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2271,7 +2272,7 @@ namespace Tests
             HasNext(e, 1);
             HasNext(e, 2);
             HasNext(e, 3);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2304,7 +2305,7 @@ namespace Tests
             var xs = new[] { 2, 3 }.ToAsyncEnumerable().Expand(x => { throw ex; });
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2315,7 +2316,7 @@ namespace Tests
             var e = xs.GetEnumerator();
             HasNext(e, 2);
             HasNext(e, 3);
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NullReferenceException);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is NullReferenceException);
         }
 
         [Fact]
@@ -2358,7 +2359,7 @@ namespace Tests
             var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Scan(8, (x, y) => { throw ex; });
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2368,7 +2369,7 @@ namespace Tests
             var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Scan((x, y) => { throw ex; });
 
             var e = xs.GetEnumerator();
-            AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
         [Fact]
@@ -2432,7 +2433,7 @@ namespace Tests
             new int[] { 1, 2, 3, 4 }.ToAsyncEnumerable()
                 .TakeLast(0)
                 .ForEachAsync(_ => { isSet = true; })
-                .Wait();
+                .Wait(WaitTimeoutMs);
 
             Assert.False(isSet);
 

+ 8 - 0
Ix.NET/Source/Tests/AsyncTests.cs

@@ -6,6 +6,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace Tests
@@ -19,6 +20,13 @@ namespace Tests
             Assert.Throws<E>(a);
         }
 
+        [Obsolete("Don't use this, use Assert.ThrowsAsync and await it", true)]
+        public Task AssertThrows<E>(Func<Task> func)
+            where E : Exception
+        {
+            return Assert.ThrowsAsync<E>(func);
+        }
+
         public void AssertThrows<E>(Action a, Func<E, bool> assert)
             where E : Exception
         {

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff