Browse Source

merge from master

Oren Novotny 7 years ago
parent
commit
741e9660c8
100 changed files with 29172 additions and 2 deletions
  1. 159 1
      .editorconfig
  2. 4 0
      .github/release-drafter.yml
  3. 7 1
      .gitignore
  4. 16 0
      AsyncRx.NET/ApiCompare/ApiCompare.csproj
  5. 49 0
      AsyncRx.NET/ApiCompare/Program.cs
  6. 194 0
      AsyncRx.NET/AsyncRx.NET.sln
  7. 16 0
      AsyncRx.NET/Playground/Playground.csproj
  8. 300 0
      AsyncRx.NET/Playground/Program.cs
  9. 13 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System.Reactive.Async.Concurrency.csproj
  10. 248 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/AsyncScheduler.cs
  11. 81 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/AsyncSchedulerBase.cs
  12. 13 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/Clock.cs
  13. 20 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/ImmediateAsyncScheduler.cs
  14. 37 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/SynchronizationContextAsyncScheduler.cs
  15. 50 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/TaskPoolAsyncScheduler.cs
  16. 155 0
      AsyncRx.NET/System.Reactive.Async.Concurrency/System/Threading/Tasks/TaskAwaitable.cs
  17. 13 0
      AsyncRx.NET/System.Reactive.Async.Core/System.Reactive.Async.Core.csproj
  18. 108 0
      AsyncRx.NET/System.Reactive.Async.Core/System/AsyncObservableExtensions.cs
  19. 29 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObservable.cs
  20. 210 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObservableBase.cs
  21. 35 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObserver.cs
  22. 82 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObserverBase.cs
  23. 28 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/Subjects/AnonymousAsyncSubject.cs
  24. 19 0
      AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/Subjects/AsyncSubject.cs
  25. 12 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System.Reactive.Async.Disposables.csproj
  26. 39 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/AsyncDisposable.cs
  27. 36 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/CancellationAsyncDisposable.cs
  28. 110 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/CompositeAsyncDisposable.cs
  29. 103 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/RefCountAsyncDisposable.cs
  30. 69 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/SerialAsyncDisposable.cs
  31. 37 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/SingleAssignmentAsyncDisposable.cs
  32. 98 0
      AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/StableCompositeAsyncDisposable.cs
  33. 7 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System.Reactive.Async.Interfaces.csproj
  34. 13 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncDisposable.cs
  35. 13 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncObservable.cs
  36. 15 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncObserver.cs
  37. 16 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Concurrency/IAsyncScheduler.cs
  38. 11 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Concurrency/IClock.cs
  39. 11 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Linq/IGroupedAsyncObservable.cs
  40. 14 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Subjects/IAsyncSubject.cs
  41. 13 0
      AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Subjects/IConnectableAsyncObservable.cs
  42. 143 0
      AsyncRx.NET/System.Reactive.Async.Linq/System.Reactive.Async.Linq.csproj
  43. 26 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/AsyncQueueLockAsyncObserver.cs
  44. 27 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventPatternSource.cs
  45. 126 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventPatternSourceBase.cs
  46. 97 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventSource.cs
  47. 73 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/Lookup.cs
  48. 1081 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.Generated.cs
  49. 90 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.Generated.tt
  50. 29 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.cs
  51. 96 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncJoinObserver.cs
  52. 665 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.Generated.cs
  53. 64 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.Generated.tt
  54. 13 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.cs
  55. 1706 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.Generated.cs
  56. 131 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.Generated.tt
  57. 35 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.cs
  58. 16 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/IAsyncJoinObserver.cs
  59. 44 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/AsyncObservable.cs
  60. 47 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/AsyncObserver.cs
  61. 37 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/GroupedAsyncObservable.cs
  62. 282 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Aggregate.cs
  63. 108 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/All.cs
  64. 288 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Amb.cs
  65. 23 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/And.cs
  66. 136 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Any.cs
  67. 319 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Append.cs
  68. 17 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/AsAsyncObservable.cs
  69. 496 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.Generated.cs
  70. 115 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.Generated.tt
  71. 579 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.cs
  72. 725 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Buffer.cs
  73. 83 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Case.cs
  74. 28 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Cast.cs
  75. 227 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Catch.cs
  76. 14662 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/CombineLatest.Generated.cs
  77. 323 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/CombineLatest.Generated.tt
  78. 137 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Concat.cs
  79. 76 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Contains.cs
  80. 94 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Count.cs
  81. 62 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DefaultIfEmpty.cs
  82. 56 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Defer.cs
  83. 138 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Delay.cs
  84. 74 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DelaySubscription.cs
  85. 32 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Dematerialize.cs
  86. 74 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Distinct.cs
  87. 225 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DistinctUntilChanged.cs
  88. 316 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Do.cs
  89. 130 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DoWhile.cs
  90. 48 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ElementAt.cs
  91. 47 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ElementAtOrDefault.cs
  92. 46 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Empty.cs
  93. 62 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Finally.cs
  94. 85 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/First.cs
  95. 86 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FirstOrDefault.cs
  96. 93 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/For.cs
  97. 132 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ForEachAsync.cs
  98. 85 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsync.cs
  99. 1398 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsyncPattern.Generated.cs
  100. 216 0
      AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsyncPattern.Generated.tt

+ 159 - 1
.editorconfig

@@ -12,6 +12,8 @@ indent_style = space
 # Code files
 # Code files
 [*.{cs,csx,vb,vbx}]
 [*.{cs,csx,vb,vbx}]
 indent_size = 4
 indent_size = 4
+insert_final_newline = true
+charset = utf-8-bom
 
 
 # Xml project files
 # Xml project files
 [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
 [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
@@ -21,14 +23,28 @@ indent_size = 2
 [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
 [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
 indent_size = 2
 indent_size = 2
 
 
+# Yml/Yaml files
+[*.{yaml,yml}]
+indent_size = 2
+
 # JSON files
 # JSON files
 [*.json]
 [*.json]
 indent_size = 2
 indent_size = 2
 
 
+# Shell scripts
+[*.sh]
+end_of_line = lf
+
+[*.{cmd,bat}]
+end_of_line = crlf
+
 # Dotnet code style settings:
 # Dotnet code style settings:
 [*.{cs,vb}]
 [*.{cs,vb}]
 # Sort using and Import directives with System.* appearing first
 # Sort using and Import directives with System.* appearing first
 dotnet_sort_system_directives_first = true
 dotnet_sort_system_directives_first = true
+# Put a blank line between System.* and Microsoft.*
+dotnet_separate_import_directive_groups = true
+
 # Avoid "this." and "Me." if not necessary
 # Avoid "this." and "Me." if not necessary
 dotnet_style_qualification_for_field = false:suggestion
 dotnet_style_qualification_for_field = false:suggestion
 dotnet_style_qualification_for_property = false:suggestion
 dotnet_style_qualification_for_property = false:suggestion
@@ -39,20 +55,130 @@ dotnet_style_qualification_for_event = false:suggestion
 dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
 dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
 dotnet_style_predefined_type_for_member_access = true:suggestion
 dotnet_style_predefined_type_for_member_access = true:suggestion
 
 
+# Prefer read-only on fields
+dotnet_style_readonly_field = true:warning
+
 # Suggest more modern language features when available
 # Suggest more modern language features when available
 dotnet_style_object_initializer = true:suggestion
 dotnet_style_object_initializer = true:suggestion
 dotnet_style_collection_initializer = true:suggestion
 dotnet_style_collection_initializer = true:suggestion
 dotnet_style_coalesce_expression = true:suggestion
 dotnet_style_coalesce_expression = true:suggestion
 dotnet_style_null_propagation = true:suggestion
 dotnet_style_null_propagation = true:suggestion
 dotnet_style_explicit_tuple_names = true:suggestion
 dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = false
+dotnet_style_prefer_conditional_expression_over_assignment = false
+dotnet_style_prefer_auto_properties = true
+
+# Accessibility modifiers
+dotnet_style_require_accessibility_modifiers = always:suggestion
+
+
+# Naming Rules
+
+# Interfaces start with an I and are PascalCased
+dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.symbols                        = interface_symbols
+dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.style                          = pascal_case_and_prefix_with_I_style
+dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.severity                       = warning
+
+# External members are PascalCased
+dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.symbols                            = externally_visible_symbols
+dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.style                              = pascal_case_style
+dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.severity                           = warning
+
+# Parameters are camelCased
+dotnet_naming_rule.parameters_must_be_camel_cased.symbols                                             = parameter_symbols
+dotnet_naming_rule.parameters_must_be_camel_cased.style                                               = camel_case_style
+dotnet_naming_rule.parameters_must_be_camel_cased.severity                                            = warning
+
+# Constants are PascalCased
+dotnet_naming_rule.constants_must_be_pascal_cased.symbols                                             = constant_symbols
+dotnet_naming_rule.constants_must_be_pascal_cased.style                                               = pascal_case_style
+dotnet_naming_rule.constants_must_be_pascal_cased.severity                                            = warning
+
+# Uncomment this group and comment out the next group if you prefer s_ prefixes for static fields
+
+# Private static fields are prefixed with s_ and are camelCased like s_myStatic
+#dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.symbols   = private_static_field_symbols
+#dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.style     = camel_case_and_prefix_with_s_underscore_style
+#dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.severity  = warning
+
+# Static readonly fields are PascalCased
+dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.symbols                               = private_static_readonly_field_symbols
+dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.style                                 = pascal_case_style
+dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.severity                              = warning
+
+# Comment this group and uncomment out the next group if you don't want _ prefixed fields.
+
+# Private instance fields are camelCased with an _ like _myField
+dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.symbols   = private_field_symbols
+dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.style     = camel_case_and_prefix_with_underscore_style
+dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.severity  = warning
+
+# Private instance fields are camelCased
+#dotnet_naming_rule.private_instance_fields_must_be_camel_cased.symbols                                = private_field_symbols
+#dotnet_naming_rule.private_instance_fields_must_be_camel_cased.style                                  = camel_case_style
+#dotnet_naming_rule.private_instance_fields_must_be_camel_cased.severity                               = warning
+
+# Symbols
+dotnet_naming_symbols.externally_visible_symbols.applicable_kinds                                     = class,struct,interface,enum,property,method,field,event,delegate
+dotnet_naming_symbols.externally_visible_symbols.applicable_accessibilities                           = public,internal,friend,protected,protected_internal,protected_friend,private_protected
+
+dotnet_naming_symbols.interface_symbols.applicable_kinds                                              = interface
+dotnet_naming_symbols.interface_symbols.applicable_accessibilities                                    = *
+
+dotnet_naming_symbols.parameter_symbols.applicable_kinds                                              = parameter
+dotnet_naming_symbols.parameter_symbols.applicable_accessibilities                                    = *
+
+dotnet_naming_symbols.constant_symbols.applicable_kinds                                               = field
+dotnet_naming_symbols.constant_symbols.required_modifiers                                             = const
+dotnet_naming_symbols.constant_symbols.applicable_accessibilities                                     = *
+
+dotnet_naming_symbols.private_static_field_symbols.applicable_kinds                                   = field
+dotnet_naming_symbols.private_static_field_symbols.required_modifiers                                 = static,shared
+dotnet_naming_symbols.private_static_field_symbols.applicable_accessibilities                         = private
+
+dotnet_naming_symbols.private_static_readonly_field_symbols.applicable_kinds                          = field
+dotnet_naming_symbols.private_static_readonly_field_symbols.required_modifiers                        = static,shared,readonly
+dotnet_naming_symbols.private_static_readonly_field_symbols.applicable_accessibilities                = private
+
+dotnet_naming_symbols.private_field_symbols.applicable_kinds                                          = field
+dotnet_naming_symbols.private_field_symbols.applicable_accessibilities                                = private
+
+# Styles
+dotnet_naming_style.camel_case_style.capitalization                                                   = camel_case
+
+dotnet_naming_style.pascal_case_style.capitalization                                                  = pascal_case
+
+dotnet_naming_style.camel_case_and_prefix_with_s_underscore_style.required_prefix                     = s_
+dotnet_naming_style.camel_case_and_prefix_with_s_underscore_style.capitalization                      = camel_case
+
+dotnet_naming_style.camel_case_and_prefix_with_underscore_style.required_prefix                       = _
+dotnet_naming_style.camel_case_and_prefix_with_underscore_style.capitalization                        = camel_case
+
+dotnet_naming_style.pascal_case_and_prefix_with_I_style.required_prefix                               = I
+dotnet_naming_style.pascal_case_and_prefix_with_I_style.capitalization                                = pascal_case
+
 
 
 # CSharp code style settings:
 # CSharp code style settings:
 [*.cs]
 [*.cs]
+# Indentation preferences
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+
 # Prefer "var" everywhere
 # Prefer "var" everywhere
 csharp_style_var_for_built_in_types = true:suggestion
 csharp_style_var_for_built_in_types = true:suggestion
 csharp_style_var_when_type_is_apparent = true:suggestion
 csharp_style_var_when_type_is_apparent = true:suggestion
 csharp_style_var_elsewhere = true:suggestion
 csharp_style_var_elsewhere = true:suggestion
 
 
+# Code style defaults
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = true
+
 # Prefer method-like constructs to have a block body
 # Prefer method-like constructs to have a block body
 csharp_style_expression_bodied_methods = false:none
 csharp_style_expression_bodied_methods = false:none
 csharp_style_expression_bodied_constructors = false:none
 csharp_style_expression_bodied_constructors = false:none
@@ -63,10 +189,17 @@ csharp_style_expression_bodied_properties = true:none
 csharp_style_expression_bodied_indexers = true:none
 csharp_style_expression_bodied_indexers = true:none
 csharp_style_expression_bodied_accessors = true:none
 csharp_style_expression_bodied_accessors = true:none
 
 
-# Suggest more modern language features when available
+# Expression 
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+
+# Pattern matching
 csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
 csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
 csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
 csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
 csharp_style_inlined_variable_declaration = true:suggestion
 csharp_style_inlined_variable_declaration = true:suggestion
+
+# Null checking preferences
 csharp_style_throw_expression = true:suggestion
 csharp_style_throw_expression = true:suggestion
 csharp_style_conditional_delegate_call = true:suggestion
 csharp_style_conditional_delegate_call = true:suggestion
 
 
@@ -77,3 +210,28 @@ csharp_new_line_before_catch = true
 csharp_new_line_before_finally = true
 csharp_new_line_before_finally = true
 csharp_new_line_before_members_in_object_initializers = true
 csharp_new_line_before_members_in_object_initializers = true
 csharp_new_line_before_members_in_anonymous_types = true
 csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = do_not_ignore
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false

+ 4 - 0
.github/release-drafter.yml

@@ -0,0 +1,4 @@
+template: |
+  ## What's Changed
+
+  $CHANGES

+ 7 - 1
.gitignore

@@ -1,4 +1,5 @@
 Ix.NET/Layout
 Ix.NET/Layout
+Ix.NET/Layout
 Rx.NET/Layout
 Rx.NET/Layout
 
 
 
 
@@ -15,6 +16,10 @@ local.properties
 .classpath
 .classpath
 .settings/
 .settings/
 .loadpath
 .loadpath
+*.exe
+.store/
+
+*.binlog
 
 
 # External tool builders
 # External tool builders
 .externalToolBuilders/
 .externalToolBuilders/
@@ -111,13 +116,14 @@ stylecop.*
 *.lock.json
 *.lock.json
 artifacts/
 artifacts/
 Generated_Code #added for RIA/Silverlight projects
 Generated_Code #added for RIA/Silverlight projects
+ApiApprovalTests.*.received.txt
 
 
 # Backup & report files from converting an old project file to a newer
 # Backup & report files from converting an old project file to a newer
 # Visual Studio version. Backup files are not needed, because we have git ;-)
 # Visual Studio version. Backup files are not needed, because we have git ;-)
 _UpgradeReport_Files/
 _UpgradeReport_Files/
 Backup*/
 Backup*/
 UpgradeLog*.XML
 UpgradeLog*.XML
-
+UpgradeLog*.htm
 
 
 
 
 ############
 ############

+ 16 - 0
AsyncRx.NET/ApiCompare/ApiCompare.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="System.Reactive" Version="4.0.0-preview00001" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async\System.Reactive.Async.csproj" />
+  </ItemGroup>
+
+</Project>

+ 49 - 0
AsyncRx.NET/ApiCompare/Program.cs

@@ -0,0 +1,49 @@
+// 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.Linq;
+using System.Reactive.Linq;
+using System.Reflection;
+
+namespace ApiCompare
+{
+    class Program
+    {
+        static void Main()
+        {
+            var observable = typeof(Observable).GetMethods(BindingFlags.Public | BindingFlags.Static).Select(m => m.Name).Distinct();
+            var asyncObservable = typeof(AsyncObservable).GetMethods(BindingFlags.Public | BindingFlags.Static).Select(m => m.Name).Distinct();
+
+            var exclude = new[]
+            {
+                "AsObservable",  // Trivially renamed to AsAsyncObservable.
+                "ToObservable",  // Trivially renamed to ToAsyncObservable.
+
+                "Subscribe",  // Trivially renamed to SubscribeAsync.
+
+                "Collect",        // Postponing push-to-pull adapters.
+                "Chunkify",       // Postponing push-to-pull adapters.
+                "GetEnumerator",  // Postponing push-to-pull adapters.
+                "Latest",         // Postponing push-to-pull adapters.
+                "MostRecent",     // Postponing push-to-pull adapters.
+                "Next",           // Postponing push-to-pull adapters.
+                "ToEnumerable",   // Postponing push-to-pull adapters.
+
+                "ForEach",  // Deprecating blocking functionality.
+                "Wait",     // Deprecating blocking functionality.
+            };
+
+            var missing = observable.Except(exclude).Except(asyncObservable).OrderBy(m => m);
+
+            foreach (var m in missing)
+            {
+                Console.WriteLine(m);
+            }
+
+            Console.WriteLine();
+            Console.WriteLine("Count = " + missing.Count());
+        }
+    }
+}

+ 194 - 0
AsyncRx.NET/AsyncRx.NET.sln

@@ -0,0 +1,194 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.3
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{1D64A210-F73A-4F91-9598-4C51865D105D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async", "System.Reactive.Async\System.Reactive.Async.csproj", "{AEDF2B02-F301-4AC6-9DBC-2744746D816A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dev", "dev", "{7D5B343C-B34D-481C-8774-B6BB14BC1B22}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Playground", "Playground\Playground.csproj", "{3B83795B-9870-43FA-82AF-95A44CF0194F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiCompare", "ApiCompare\ApiCompare.csproj", "{84F35A01-ECC4-4635-B702-77F6B18FD54C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Shared", "System.Reactive.Shared\System.Reactive.Shared.csproj", "{09F10630-405B-4270-9AB6-0AB8F2EE6621}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Concurrency", "System.Reactive.Async.Concurrency\System.Reactive.Async.Concurrency.csproj", "{2794CB27-C6A2-4156-A919-C033A9EE474E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Disposables", "System.Reactive.Async.Disposables\System.Reactive.Async.Disposables.csproj", "{CE5036FE-9B94-40CC-8084-26ACE74D806A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Interfaces", "System.Reactive.Async.Interfaces\System.Reactive.Async.Interfaces.csproj", "{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Subjects", "System.Reactive.Async.Subjects\System.Reactive.Async.Subjects.csproj", "{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Linq", "System.Reactive.Async.Linq\System.Reactive.Async.Linq.csproj", "{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Bcl", "System.Reactive.Bcl\System.Reactive.Bcl.csproj", "{B709ED34-B782-4617-AE83-C0170A2EEE19}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reactive.Async.Core", "System.Reactive.Async.Core\System.Reactive.Async.Core.csproj", "{9D2E636E-1C4D-4130-908D-4174B6D7AC71}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|x64.Build.0 = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Debug|x86.Build.0 = Debug|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|x64.ActiveCfg = Release|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|x64.Build.0 = Release|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|x86.ActiveCfg = Release|Any CPU
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A}.Release|x86.Build.0 = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|x64.Build.0 = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Debug|x86.Build.0 = Debug|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|x64.ActiveCfg = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|x64.Build.0 = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|x86.ActiveCfg = Release|Any CPU
+		{3B83795B-9870-43FA-82AF-95A44CF0194F}.Release|x86.Build.0 = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|x64.Build.0 = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Debug|x86.Build.0 = Debug|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|x64.ActiveCfg = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|x64.Build.0 = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|x86.ActiveCfg = Release|Any CPU
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C}.Release|x86.Build.0 = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|x64.Build.0 = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Debug|x86.Build.0 = Debug|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|Any CPU.Build.0 = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|x64.ActiveCfg = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|x64.Build.0 = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|x86.ActiveCfg = Release|Any CPU
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621}.Release|x86.Build.0 = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|x64.Build.0 = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Debug|x86.Build.0 = Debug|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|x64.ActiveCfg = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|x64.Build.0 = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|x86.ActiveCfg = Release|Any CPU
+		{2794CB27-C6A2-4156-A919-C033A9EE474E}.Release|x86.Build.0 = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|x64.Build.0 = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Debug|x86.Build.0 = Debug|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|x64.ActiveCfg = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|x64.Build.0 = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|x86.ActiveCfg = Release|Any CPU
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A}.Release|x86.Build.0 = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|x64.Build.0 = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Debug|x86.Build.0 = Debug|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|x64.ActiveCfg = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|x64.Build.0 = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|x86.ActiveCfg = Release|Any CPU
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE}.Release|x86.Build.0 = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|x64.Build.0 = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Debug|x86.Build.0 = Debug|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|x64.ActiveCfg = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|x64.Build.0 = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|x86.ActiveCfg = Release|Any CPU
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0}.Release|x86.Build.0 = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|x64.Build.0 = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Debug|x86.Build.0 = Debug|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|x64.ActiveCfg = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|x64.Build.0 = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|x86.ActiveCfg = Release|Any CPU
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D}.Release|x86.Build.0 = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|x64.Build.0 = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Debug|x86.Build.0 = Debug|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|x64.ActiveCfg = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|x64.Build.0 = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|x86.ActiveCfg = Release|Any CPU
+		{B709ED34-B782-4617-AE83-C0170A2EEE19}.Release|x86.Build.0 = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|x64.Build.0 = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Debug|x86.Build.0 = Debug|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|x64.ActiveCfg = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|x64.Build.0 = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|x86.ActiveCfg = Release|Any CPU
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{AEDF2B02-F301-4AC6-9DBC-2744746D816A} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{3B83795B-9870-43FA-82AF-95A44CF0194F} = {7D5B343C-B34D-481C-8774-B6BB14BC1B22}
+		{84F35A01-ECC4-4635-B702-77F6B18FD54C} = {7D5B343C-B34D-481C-8774-B6BB14BC1B22}
+		{09F10630-405B-4270-9AB6-0AB8F2EE6621} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{2794CB27-C6A2-4156-A919-C033A9EE474E} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{CE5036FE-9B94-40CC-8084-26ACE74D806A} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{B66081C4-2DE2-451C-AE3B-6D2A8B9BE0EE} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{31A2470C-29B0-45BD-A9E8-340E7BDA15B0} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{D3A5AA1A-1E6F-43FD-B827-3015429D6E6D} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{B709ED34-B782-4617-AE83-C0170A2EEE19} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+		{9D2E636E-1C4D-4130-908D-4174B6D7AC71} = {1D64A210-F73A-4F91-9598-4C51865D105D}
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {836C3B9A-682A-4E6F-8053-92BFC9D29D89}
+	EndGlobalSection
+EndGlobal

+ 16 - 0
AsyncRx.NET/Playground/Playground.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <LangVersion>7.1</LangVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async\System.Reactive.Async.csproj" />
+  </ItemGroup>
+
+</Project>

+ 300 - 0
AsyncRx.NET/Playground/Program.cs

@@ -0,0 +1,300 @@
+// 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.Linq;
+using System.Reactive;
+using System.Reactive.Concurrency;
+using System.Reactive.Linq;
+using System.Reactive.Subjects;
+using System.Threading.Tasks;
+
+namespace Playground
+{
+    static class Program
+    {
+        static void Main()
+        {
+            MainAsync().GetAwaiter().GetResult();
+
+            Console.ReadLine();
+        }
+
+        static async Task MainAsync()
+        {
+            //await AggregateAsync();
+            //await AllAsync();
+            //await AnyAsync();
+            //await AppendAsync();
+            //await AwaitAsync();
+            //await BufferTimeHoppingAsync();
+            //await BufferTimeSlidingAsync();
+            //await CombineLatestAsync();
+            //await ConcatAsync();
+            //await DelayAsync();
+            //await GroupByAsync();
+            //await GroupBySelectManyAsync();
+            //await MergeAsync();
+            //await PrependAsync();
+            //await RangeAsync();
+            //await ReplaySubjectAsync();
+            //await ReturnAsync();
+            //await SelectManyAsync();
+            //await SubjectAsync();
+            //await TakeUntilAsync();
+            //await TimerAsync();
+            //await WhileAsync();
+        }
+
+        static async Task AggregateAsync()
+        {
+            await AsyncObservable.Range(0, 10).Aggregate(0, (sum, x) => sum + x).SubscribeAsync(Print<int>());
+        }
+
+        static async Task AllAsync()
+        {
+            await AsyncObservable.Range(0, 10).All(x => x < 10).SubscribeAsync(Print<bool>());
+        }
+
+        static async Task AnyAsync()
+        {
+            await AsyncObservable.Range(0, 10).Any(x => x == 5).SubscribeAsync(Print<bool>());
+        }
+
+        static async Task AppendAsync()
+        {
+            await AsyncObservable.Range(0, 10).Append(42).SubscribeAsync(Print<int>());
+        }
+
+        static async Task AwaitAsync()
+        {
+            Console.WriteLine(await AsyncObservable.Range(0, 10));
+        }
+
+        static async Task BufferTimeHoppingAsync()
+        {
+            await
+                AsyncObservable
+                    .Interval(TimeSpan.FromMilliseconds(300))
+                    .Buffer(TimeSpan.FromSeconds(1))
+                    .Select(xs => string.Join(", ", xs))
+                    .SubscribeAsync(Print<string>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task BufferTimeSlidingAsync()
+        {
+            await
+                AsyncObservable
+                    .Interval(TimeSpan.FromMilliseconds(100))
+                    .Timestamp(TaskPoolAsyncScheduler.Default)
+                    .Buffer(TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(300))
+                    .Select(xs => $"[{xs.First().Timestamp}, {xs.Last().Timestamp}] = {(xs.Last().Timestamp - xs.First().Timestamp).TotalMilliseconds}")
+                    .SubscribeAsync(Print<string>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task CombineLatestAsync()
+        {
+            await
+                AsyncObservable.CombineLatest(
+                    AsyncObservable.Interval(TimeSpan.FromMilliseconds(250)).Take(10).Timestamp(),
+                    AsyncObservable.Interval(TimeSpan.FromMilliseconds(333)).Take(10).Timestamp(),
+                    (x, y) => x.ToString() + ", " + y.ToString()
+                )
+                .SubscribeAsync(Print<string>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task ConcatAsync()
+        {
+            await
+                AsyncObservable.Concat(
+                    AsyncObservable.Range(0, 5),
+                    AsyncObservable.Range(5, 5),
+                    AsyncObservable.Range(10, 5),
+                    AsyncObservable.Range(15, 5)
+                )
+                .SubscribeAsync(Print<int>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task DelayAsync()
+        {
+            await
+                AsyncObservable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
+                    .Timestamp()
+                    .Delay(TimeSpan.FromMilliseconds(2500))
+                    .Timestamp()
+                    .Select(x => new TimeInterval<long>(x.Value.Value, x.Timestamp - x.Value.Timestamp).ToString())
+                    .SubscribeAsync(Print<string>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task GroupByAsync()
+        {
+            await
+                AsyncObservable.Interval(TimeSpan.FromMilliseconds(250))
+                    .Timestamp()
+                    .Take(20)
+                    .GroupBy(t => t.Timestamp.Millisecond / 100)
+                    .SubscribeAsync(async g =>
+                    {
+                        await g.Select(x => g.Key + " - " + x).SubscribeAsync(Print<string>());
+                    });
+        }
+
+        static async Task GroupBySelectManyAsync()
+        {
+            await
+                AsyncObservable.Interval(TimeSpan.FromMilliseconds(250))
+                    .Timestamp()
+                    .Take(20)
+                    .GroupBy(t => t.Timestamp.Millisecond / 100)
+                    .SelectMany(g => g, (g, x) => g.Key + " - " + x)
+                    .SubscribeAsync(Print<string>());
+        }
+
+        static async Task MergeAsync()
+        {
+            var subject = new SequentialSimpleAsyncSubject<IAsyncObservable<int>>();
+
+            var res = subject.Merge();
+
+            await res.SubscribeAsync(Print<int>());
+
+            for (var i = 1; i <= 10; i++)
+            {
+                await subject.OnNextAsync(AsyncObservable.Range(0, i));
+            }
+
+            await subject.OnCompletedAsync();
+        }
+
+        static async Task PrependAsync()
+        {
+            await AsyncObservable.Range(0, 10).Prepend(42).SubscribeAsync(Print<int>());
+        }
+
+        static async Task RangeAsync()
+        {
+            await AsyncObservable.Range(0, 10).SubscribeAsync(PrintAsync<int>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task ReplaySubjectAsync()
+        {
+            var sub = new SequentialReplayAsyncSubject<int>(5);
+
+            var d1 = await sub.SubscribeAsync(x => Console.WriteLine("1> " + x));
+
+            await sub.OnNextAsync(40);
+            await sub.OnNextAsync(41);
+
+            var d2 = await sub.SubscribeAsync(x => Console.WriteLine("2> " + x));
+
+            await sub.OnNextAsync(42);
+
+            await d1.DisposeAsync();
+
+            await sub.OnNextAsync(43);
+
+            var d3 = await sub.SubscribeAsync(x => Console.WriteLine("3> " + x));
+
+            await sub.OnNextAsync(44);
+            await sub.OnNextAsync(45);
+
+            await d3.DisposeAsync();
+
+            await sub.OnNextAsync(46);
+
+            await d2.DisposeAsync();
+
+            await sub.OnNextAsync(47);
+        }
+
+        static async Task ReturnAsync()
+        {
+            await AsyncObservable.Return(42).SubscribeAsync(Print<int>());
+        }
+
+        static async Task SelectManyAsync()
+        {
+            var res = from i in AsyncObservable.Range(0, 10)
+                      from j in AsyncObservable.Range(i * 10, 10)
+                      select i + " -> " + j;
+
+            await res.SubscribeAsync(Print<string>());
+        }
+
+        static async Task SubjectAsync()
+        {
+            var subject = new SequentialSimpleAsyncSubject<int>();
+
+            var res = subject.Where(x => x % 2 == 0).Select(x => x + 1);
+
+            await res.SubscribeAsync(Print<int>());
+
+            for (var i = 0; i < 10; i++)
+            {
+                await subject.OnNextAsync(i);
+            }
+
+            await subject.OnCompletedAsync();
+        }
+
+        static async Task TakeUntilAsync()
+        {
+            await AsyncObservable.Range(0, int.MaxValue).TakeUntil(DateTimeOffset.Now.AddSeconds(5)).SubscribeAsync(Print<int>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task TimerAsync()
+        {
+            await AsyncObservable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2)).Take(5).Select(_ => DateTimeOffset.Now).SubscribeAsync(Print<DateTimeOffset>()); // TODO: Use ForEachAsync.
+        }
+
+        static async Task WhileAsync()
+        {
+            var i = 0;
+
+            await AsyncObservable.While(() => ++i < 5, AsyncObservable.Range(0, 5)).SubscribeAsync(Print<int>()); // TODO: Use ForEachAsync.
+        }
+
+        static IAsyncObserver<T> Print<T>()
+        {
+            return AsyncObserver.Create<T>(
+                x =>
+                {
+                    Console.WriteLine(x);
+                    return Task.CompletedTask;
+                },
+                ex =>
+                {
+                    Console.WriteLine("Error: " + ex);
+                    return Task.CompletedTask;
+                },
+                () =>
+                {
+                    Console.WriteLine("Completed");
+                    return Task.CompletedTask;
+                }
+            );
+        }
+
+        static IAsyncObserver<T> PrintAsync<T>()
+        {
+            return AsyncObserver.Create<T>(
+                async x =>
+                {
+                    await Task.Yield();
+                    Console.WriteLine(x);
+                },
+                async ex =>
+                {
+                    await Task.Yield();
+                    Console.WriteLine("Error: " + ex);
+                },
+                async () =>
+                {
+                    await Task.Yield();
+                    Console.WriteLine("Completed");
+                }
+            );
+        }
+    }
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System.Reactive.Async.Concurrency.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async.Interfaces\System.Reactive.Async.Interfaces.csproj" />
+    <ProjectReference Include="..\System.Reactive.Bcl\System.Reactive.Bcl.csproj" />
+    <ProjectReference Include="..\System.Reactive.Shared\System.Reactive.Shared.csproj" />
+  </ItemGroup>
+
+</Project>

+ 248 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/AsyncScheduler.cs

@@ -0,0 +1,248 @@
+// 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.Runtime.ExceptionServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public static class AsyncScheduler
+    {
+        public static IAwaitable RendezVous(this IAsyncScheduler scheduler)
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return new RendezVousAwaitable(scheduler, CancellationToken.None);
+        }
+
+        public static IAwaitable RendezVous(this IAsyncScheduler scheduler, CancellationToken token)
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            token.ThrowIfCancellationRequested();
+
+            return new RendezVousAwaitable(scheduler, token);
+        }
+
+        public static IAwaitable RendezVous(this Task task, IAsyncScheduler scheduler) => RendezVous(task, scheduler, CancellationToken.None);
+
+        public static IAwaitable RendezVous(this Task task, IAsyncScheduler scheduler, CancellationToken token)
+        {
+            if (task == null)
+                throw new ArgumentNullException(nameof(task));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return new TaskAwaitable(task, false, scheduler, token);
+        }
+
+        public static IAwaitable<T> RendezVous<T>(this Task<T> task, IAsyncScheduler scheduler) => RendezVous(task, scheduler, CancellationToken.None);
+
+        public static IAwaitable<T> RendezVous<T>(this Task<T> task, IAsyncScheduler scheduler, CancellationToken token)
+        {
+            if (task == null)
+                throw new ArgumentNullException(nameof(task));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return new TaskAwaitable<T>(task, false, scheduler, token);
+        }
+
+        public static async Task Delay(this IAsyncScheduler scheduler, TimeSpan dueTime, CancellationToken token = default(CancellationToken))
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            var tcs = new TaskCompletionSource<bool>();
+
+            var task = await scheduler.ScheduleAsync(ct =>
+            {
+                if (ct.IsCancellationRequested)
+                {
+                    tcs.TrySetCanceled(ct);
+                }
+                else
+                {
+                    tcs.SetResult(true);
+                }
+
+                return Task.CompletedTask;
+            }, dueTime);
+
+            using (token.Register(() => task.DisposeAsync()))
+            {
+                await tcs.Task;
+            }
+        }
+
+        public static async Task Delay(this IAsyncScheduler scheduler, DateTimeOffset dueTime, CancellationToken token = default(CancellationToken))
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            var tcs = new TaskCompletionSource<bool>();
+
+            var task = await scheduler.ScheduleAsync(ct =>
+            {
+                if (ct.IsCancellationRequested)
+                {
+                    tcs.TrySetCanceled(ct);
+                }
+                else
+                {
+                    tcs.SetResult(true);
+                }
+
+                return Task.CompletedTask;
+            }, dueTime);
+
+            using (token.Register(() => task.DisposeAsync()))
+            {
+                await tcs.Task;
+            }
+        }
+
+        public static async Task ExecuteAsync(this IAsyncScheduler scheduler, Func<CancellationToken, Task> action, CancellationToken token = default(CancellationToken))
+        {
+            var tcs = new TaskCompletionSource<object>();
+
+            var d = await scheduler.ScheduleAsync(async ct =>
+            {
+                try
+                {
+                    ct.ThrowIfCancellationRequested();
+
+                    await action(ct).RendezVous(scheduler, ct);
+                }
+                catch (OperationCanceledException ex) when (ex.CancellationToken == ct)
+                {
+                    tcs.TrySetCanceled(ct);
+                }
+                catch (Exception ex)
+                {
+                    tcs.TrySetException(ex);
+                }
+                finally
+                {
+                    tcs.TrySetResult(null);
+                }
+            });
+
+            using (token.Register(() =>
+            {
+                try
+                {
+                    d.DisposeAsync();
+                }
+                finally
+                {
+                    tcs.TrySetCanceled(token);
+                }
+            }))
+            {
+                await tcs.Task.ConfigureAwait(false);
+            }
+        }
+
+        public static async Task<TResult> ExecuteAsync<TResult>(this IAsyncScheduler scheduler, Func<CancellationToken, Task<TResult>> action, CancellationToken token = default(CancellationToken))
+        {
+            var tcs = new TaskCompletionSource<TResult>();
+
+            var d = await scheduler.ScheduleAsync(async ct =>
+            {
+                var res = default(TResult);
+
+                try
+                {
+                    ct.ThrowIfCancellationRequested();
+
+                    res = await action(ct).RendezVous(scheduler, ct);
+                }
+                catch (OperationCanceledException ex) when (ex.CancellationToken == ct)
+                {
+                    tcs.TrySetCanceled(ct);
+                }
+                catch (Exception ex)
+                {
+                    tcs.TrySetException(ex);
+                }
+                finally
+                {
+                    tcs.TrySetResult(res);
+                }
+            });
+
+            using (token.Register(() =>
+            {
+                try
+                {
+                    d.DisposeAsync();
+                }
+                finally
+                {
+                    tcs.TrySetCanceled(token);
+                }
+            }))
+            {
+                return await tcs.Task.ConfigureAwait(false);
+            }
+        }
+
+        private sealed class RendezVousAwaitable : IAwaitable, IAwaiter // PERF: Can we avoid these allocations?
+        {
+            private readonly IAsyncScheduler _scheduler;
+            private readonly CancellationToken _token;
+
+            private bool _done;
+            private ExceptionDispatchInfo _error;
+
+            public RendezVousAwaitable(IAsyncScheduler scheduler, CancellationToken token)
+            {
+                _scheduler = scheduler;
+                _token = token;
+            }
+
+            public bool IsCompleted => _done;
+
+            public IAwaiter GetAwaiter() => this;
+
+            public void GetResult()
+            {
+                if (!_done)
+                {
+                    throw new InvalidOperationException(); // REVIEW: No support for blocking.
+                }
+
+                if (_error != null)
+                {
+                    _error.Throw();
+                }
+            }
+
+            public void OnCompleted(Action continuation)
+            {
+                var t = _scheduler.ExecuteAsync(ct =>
+                {
+                    try
+                    {
+                        continuation();
+                    }
+                    catch (Exception ex)
+                    {
+                        _error = ExceptionDispatchInfo.Capture(ex);
+                    }
+                    finally
+                    {
+                        _done = true;
+                    }
+
+                    return Task.CompletedTask;
+                }, _token);
+            }
+        }
+    }
+}

+ 81 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/AsyncSchedulerBase.cs

@@ -0,0 +1,81 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public abstract class AsyncSchedulerBase : IAsyncScheduler
+    {
+        public virtual DateTimeOffset Now => DateTimeOffset.Now;
+
+        public virtual Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action)
+        {
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            return ScheduleAsyncCore(action);
+        }
+
+        public virtual Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action, TimeSpan dueTime)
+        {
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            var dueTimeRelative = Normalize(dueTime);
+
+            return ScheduleAsyncCore(async ct =>
+            {
+                await Delay(dueTimeRelative, ct); // NB: Honor SynchronizationContext to stay on scheduler.
+
+                await action(ct);
+            });
+        }
+
+        public virtual Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action, DateTimeOffset dueTime)
+        {
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            return ScheduleAsyncCore(async ct =>
+            {
+                var dueTimeRelative = Normalize(dueTime - Now); // TODO: Support clock drift and clock changes.
+
+                await Delay(dueTimeRelative, ct); // NB: Honor SynchronizationContext to stay on scheduler.
+
+                await action(ct);
+            });
+        }
+
+        protected virtual async Task<IAsyncDisposable> ScheduleAsyncCore(Func<CancellationToken, Task> action)
+        {
+            var cad = new CancellationAsyncDisposable();
+
+            await ScheduleAsyncCore(action, cad.Token).ConfigureAwait(false);
+
+            return cad;
+        }
+
+        protected abstract Task ScheduleAsyncCore(Func<CancellationToken, Task> action, CancellationToken token);
+
+        protected abstract Task Delay(TimeSpan dueTime, CancellationToken token);
+
+        protected static TimeSpan Normalize(TimeSpan timeSpan) => timeSpan < TimeSpan.Zero ? TimeSpan.Zero : timeSpan;
+
+        private sealed class CancellationAsyncDisposable : IAsyncDisposable
+        {
+            private readonly CancellationTokenSource _cts = new CancellationTokenSource();
+
+            public CancellationToken Token => _cts.Token;
+
+            public Task DisposeAsync()
+            {
+                _cts.Cancel();
+
+                return Task.CompletedTask;
+            }
+        }
+    }
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/Clock.cs

@@ -0,0 +1,13 @@
+// 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. 
+
+namespace System.Reactive.Concurrency
+{
+    public class Clock : IClock
+    {
+        public static Clock Default { get; } = new Clock();
+
+        public DateTimeOffset Now => DateTimeOffset.UtcNow;
+    }
+}

+ 20 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/ImmediateAsyncScheduler.cs

@@ -0,0 +1,20 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public sealed class ImmediateAsyncScheduler : AsyncSchedulerBase
+    {
+        public static ImmediateAsyncScheduler Instance { get; } = new ImmediateAsyncScheduler();
+
+        private ImmediateAsyncScheduler() { }
+
+        protected override Task Delay(TimeSpan dueTime, CancellationToken token) => Task.Delay(dueTime);
+
+        protected override Task ScheduleAsyncCore(Func<CancellationToken, Task> action, CancellationToken token) => action(token);
+    }
+}

+ 37 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/SynchronizationContextAsyncScheduler.cs

@@ -0,0 +1,37 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public sealed class SynchronizationContextAsyncScheduler : AsyncSchedulerBase
+    {
+        private readonly SynchronizationContext _context;
+
+        public SynchronizationContextAsyncScheduler(SynchronizationContext context)
+        {
+            if (context == null)
+                throw new ArgumentNullException(nameof(context));
+
+            _context = context;
+        }
+
+        protected override Task Delay(TimeSpan dueTime, CancellationToken token) => Task.Delay(dueTime, token);
+
+        protected override Task ScheduleAsyncCore(Func<CancellationToken, Task> action, CancellationToken token)
+        {
+            _context.Post(_ =>
+            {
+                if (!token.IsCancellationRequested)
+                {
+                    action(token);
+                }
+            }, null);
+
+            return Task.CompletedTask;
+        }
+    }
+}

+ 50 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Reactive/Concurrency/TaskPoolAsyncScheduler.cs

@@ -0,0 +1,50 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public sealed class TaskPoolAsyncScheduler : AsyncSchedulerBase
+    {
+        private readonly TaskFactory _factory;
+
+        public static TaskPoolAsyncScheduler Current { get; } = new TaskPoolAsyncScheduler(TaskScheduler.Current);
+        public static TaskPoolAsyncScheduler Default { get; } = new TaskPoolAsyncScheduler(TaskScheduler.Default);
+
+        public TaskPoolAsyncScheduler(TaskScheduler scheduler)
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            _factory = new TaskFactory(scheduler);
+        }
+
+        public TaskPoolAsyncScheduler(TaskFactory factory)
+        {
+            if (factory == null)
+                throw new ArgumentNullException(nameof(factory));
+
+            _factory = factory;
+        }
+
+        protected override Task Delay(TimeSpan dueTime, CancellationToken token) => Task.Delay(dueTime, token);
+
+        protected override Task ScheduleAsyncCore(Func<CancellationToken, Task> action, CancellationToken token)
+        {
+            var task = _factory.StartNew(() => action(token), token);
+
+            task.Unwrap().ContinueWith(t =>
+            {
+                if (!t.IsCanceled && t.Exception != null)
+                {
+                    // TODO: Call event handler.
+                }
+            });
+
+            return Task.CompletedTask;
+        }
+    }
+}

+ 155 - 0
AsyncRx.NET/System.Reactive.Async.Concurrency/System/Threading/Tasks/TaskAwaitable.cs

@@ -0,0 +1,155 @@
+// 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.Reactive.Concurrency;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading.Tasks
+{
+    public sealed class TaskAwaitable : IAwaitable, IAwaiter
+    {
+        private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter _task;
+        private readonly IAsyncScheduler _scheduler;
+        private readonly CancellationToken _token;
+
+        public TaskAwaitable(Task task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
+        {
+            if (task == null)
+                throw new ArgumentNullException(nameof(task));
+
+            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _scheduler = scheduler;
+            _token = token;
+        }
+
+        public bool IsCompleted => _task.IsCompleted;
+
+        public IAwaiter GetAwaiter() => this;
+
+        public void GetResult()
+        {
+            _token.ThrowIfCancellationRequested();
+
+            _task.GetResult();
+        }
+
+        public void OnCompleted(Action continuation)
+        {
+            var cancel = default(IDisposable);
+
+            if (_token.CanBeCanceled)
+            {
+                cancel = _token.Register(() =>
+                {
+                    Interlocked.Exchange(ref continuation, null)?.Invoke();
+                });
+            }
+
+            try
+            {
+                _task.OnCompleted(() =>
+                {
+                    void Invoke()
+                    {
+                        cancel?.Dispose();
+
+                        Interlocked.Exchange(ref continuation, null)?.Invoke();
+                    }
+
+                    if (_scheduler != null)
+                    {
+                        var t = _scheduler.ExecuteAsync(ct =>
+                        {
+                            Invoke();
+
+                            return Task.CompletedTask;
+                        }, _token);
+                    }
+                    else
+                    {
+                        Invoke();
+                    }
+                });
+            }
+            catch
+            {
+                cancel?.Dispose();
+                throw;
+            }
+        }
+    }
+
+    public sealed class TaskAwaitable<T> : IAwaitable<T>, IAwaiter<T>
+    {
+        private readonly ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter _task;
+        private readonly IAsyncScheduler _scheduler;
+        private readonly CancellationToken _token;
+
+        public TaskAwaitable(Task<T> task, bool continueOnCapturedContext, IAsyncScheduler scheduler, CancellationToken token)
+        {
+            if (task == null)
+                throw new ArgumentNullException(nameof(task));
+
+            _task = task.ConfigureAwait(continueOnCapturedContext).GetAwaiter();
+            _scheduler = scheduler;
+            _token = token;
+        }
+
+        public bool IsCompleted => _task.IsCompleted;
+
+        public IAwaiter<T> GetAwaiter() => this;
+
+        public T GetResult()
+        {
+            _token.ThrowIfCancellationRequested();
+
+            return _task.GetResult();
+        }
+
+        public void OnCompleted(Action continuation)
+        {
+            var cancel = default(IDisposable);
+
+            if (_token.CanBeCanceled)
+            {
+                cancel = _token.Register(() =>
+                {
+                    Interlocked.Exchange(ref continuation, null)?.Invoke();
+                });
+            }
+
+            try
+            {
+                _task.OnCompleted(() =>
+                {
+                    void Invoke()
+                    {
+                        cancel?.Dispose();
+
+                        Interlocked.Exchange(ref continuation, null)?.Invoke();
+                    }
+
+                    if (_scheduler != null)
+                    {
+                        var t = _scheduler.ExecuteAsync(ct =>
+                        {
+                            Invoke();
+
+                            return Task.CompletedTask;
+                        }, _token);
+                    }
+                    else
+                    {
+                        Invoke();
+                    }
+                });
+            }
+            catch
+            {
+                cancel?.Dispose();
+                throw;
+            }
+        }
+    }
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Core/System.Reactive.Async.Core.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async.Disposables\System.Reactive.Async.Disposables.csproj" />
+    <ProjectReference Include="..\System.Reactive.Async.Interfaces\System.Reactive.Async.Interfaces.csproj" />
+    <ProjectReference Include="..\System.Reactive.Bcl\System.Reactive.Bcl.csproj" />
+  </ItemGroup>
+
+</Project>

+ 108 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/AsyncObservableExtensions.cs

@@ -0,0 +1,108 @@
+// 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.Reactive;
+using System.Threading.Tasks;
+
+namespace System
+{
+    public static class AsyncObservableExtensions
+    {
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Func<T, Task> onNextAsync)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(onNextAsync, ex => Task.FromException(ex), () => Task.CompletedTask));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Func<T, Task> onNextAsync, Func<Exception, Task> onErrorAsync)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onErrorAsync == null)
+                throw new ArgumentNullException(nameof(onErrorAsync));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(onNextAsync, onErrorAsync, () => Task.CompletedTask));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Func<T, Task> onNextAsync, Func<Task> onCompletedAsync)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onCompletedAsync == null)
+                throw new ArgumentNullException(nameof(onCompletedAsync));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(onNextAsync, ex => Task.FromException(ex), onCompletedAsync));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Func<T, Task> onNextAsync, Func<Exception, Task> onErrorAsync, Func<Task> onCompletedAsync)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onErrorAsync == null)
+                throw new ArgumentNullException(nameof(onErrorAsync));
+            if (onCompletedAsync == null)
+                throw new ArgumentNullException(nameof(onCompletedAsync));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Action<T> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(x => { onNext(x); return Task.CompletedTask; }, ex => Task.FromException(ex), () => Task.CompletedTask));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Action<T> onNext, Action<Exception> onError)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(x => { onNext(x); return Task.CompletedTask; }, ex => { onError(ex); return Task.CompletedTask; }, () => Task.CompletedTask));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Action<T> onNext, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(x => { onNext(x); return Task.CompletedTask; }, ex => Task.FromException(ex), () => { onCompleted(); return Task.CompletedTask; }));
+        }
+
+        public static Task<IAsyncDisposable> SubscribeAsync<T>(this IAsyncObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return source.SubscribeAsync(new AsyncObserver<T>(x => { onNext(x); return Task.CompletedTask; }, ex => { onError(ex); return Task.CompletedTask; }, () => { onCompleted(); return Task.CompletedTask; }));
+        }
+    }
+}

+ 29 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObservable.cs

@@ -0,0 +1,29 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive
+{
+    public class AsyncObservable<T> : AsyncObservableBase<T>
+    {
+        private readonly Func<IAsyncObserver<T>, Task<IAsyncDisposable>> _subscribeAsync;
+
+        public AsyncObservable(Func<IAsyncObserver<T>, Task<IAsyncDisposable>> subscribeAsync)
+        {
+            if (subscribeAsync == null)
+                throw new ArgumentNullException(nameof(subscribeAsync));
+
+            _subscribeAsync = subscribeAsync;
+        }
+
+        protected override Task<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<T> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return _subscribeAsync(observer);
+        }
+    }
+}

+ 210 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObservableBase.cs

@@ -0,0 +1,210 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive
+{
+    public abstract class AsyncObservableBase<T> : IAsyncObservable<T>
+    {
+        public async Task<IAsyncDisposable> SubscribeAsync(IAsyncObserver<T> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var autoDetach = new AutoDetachAsyncObserver(observer);
+
+            var subscription = await SubscribeAsyncCore(autoDetach).ConfigureAwait(false);
+
+            await autoDetach.AssignAsync(subscription);
+
+            return autoDetach;
+        }
+
+        protected abstract Task<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<T> observer);
+
+        private sealed class AutoDetachAsyncObserver : AsyncObserverBase<T>, IAsyncDisposable
+        {
+            private readonly IAsyncObserver<T> _observer;
+            private readonly object _gate = new object();
+
+            private IAsyncDisposable _subscription;
+            private Task _task;
+            private bool _disposing;
+
+            public AutoDetachAsyncObserver(IAsyncObserver<T> observer)
+            {
+                _observer = observer;
+            }
+
+            public async Task AssignAsync(IAsyncDisposable subscription)
+            {
+                var shouldDispose = false;
+
+                lock (_gate)
+                {
+                    if (_disposing)
+                    {
+                        shouldDispose = true;
+                    }
+                    else
+                    {
+                        _subscription = subscription;
+                    }
+                }
+
+                if (shouldDispose)
+                {
+                    await subscription.DisposeAsync().ConfigureAwait(false);
+                }
+            }
+
+            public async Task DisposeAsync()
+            {
+                var task = default(Task);
+                var subscription = default(IAsyncDisposable);
+
+                lock (_gate)
+                {
+                    //
+                    // NB: The postcondition of awaiting the first DisposeAsync call to complete is that all message
+                    //     processing has ceased, i.e. no further On*AsyncCore calls will be made. This is achieved
+                    //     here by setting _disposing to true, which is checked by the On*AsyncCore calls upon
+                    //     entry, and by awaiting the task of any in-flight On*AsyncCore calls.
+                    //
+                    //     Timing of the disposal of the subscription is less deterministic due to the intersection
+                    //     with the AssignAsync code path. However, the auto-detach observer can only be returned
+                    //     from the SubscribeAsync call *after* a call to AssignAsync has been made and awaited, so
+                    //     either AssignAsync triggers the disposal and an already disposed instance is returned, or
+                    //     the user calling DisposeAsync will either encounter a busy observer which will be stopped
+                    //     in its tracks (as described above) or it will trigger a disposal of the subscription. In
+                    //     both these cases the result of awaiting DisposeAsync guarantees no further message flow.
+                    //
+
+                    if (!_disposing)
+                    {
+                        _disposing = true;
+
+                        task = _task;
+                        subscription = _subscription;
+                    }
+                }
+
+                try
+                {
+                    //
+                    // BUGBUG: This causes grief when an outgoing On*Async call reenters the DisposeAsync method and
+                    //         results in the task returned from the On*Async call to be awaited to serialize the
+                    //         call to subscription.DisposeAsync after it's done. We need to either detect reentrancy
+                    //         and queue up the call to DisposeAsync or follow an when we trigger the disposal without
+                    //         awaiting outstanding work (thus allowing for concurrency).
+                    //
+                    // if (task != null)
+                    // {
+                    //     await task.ConfigureAwait(false);
+                    // }
+                    //
+                }
+                finally
+                {
+                    if (subscription != null)
+                    {
+                        await subscription.DisposeAsync().ConfigureAwait(false);
+                    }
+                }
+            }
+
+            protected override async Task OnCompletedAsyncCore()
+            {
+                lock (_gate)
+                {
+                    if (_disposing)
+                    {
+                        return;
+                    }
+
+                    _task = _observer.OnCompletedAsync();
+                }
+
+                try
+                {
+                    await _task.ConfigureAwait(false);
+                }
+                finally
+                {
+                    await FinishAsync().ConfigureAwait(false);
+                }
+            }
+
+            protected override async Task OnErrorAsyncCore(Exception error)
+            {
+                lock (_gate)
+                {
+                    if (_disposing)
+                    {
+                        return;
+                    }
+
+                    _task = _observer.OnErrorAsync(error);
+                }
+
+                try
+                {
+                    await _task.ConfigureAwait(false);
+                }
+                finally
+                {
+                    await FinishAsync().ConfigureAwait(false);
+                }
+            }
+
+            protected override async Task OnNextAsyncCore(T value)
+            {
+                lock (_gate)
+                {
+                    if (_disposing)
+                    {
+                        return;
+                    }
+
+                    _task = _observer.OnNextAsync(value);
+                }
+
+                try
+                {
+                    await _task.ConfigureAwait(false);
+                }
+                finally
+                {
+                    lock (_gate)
+                    {
+                        _task = null;
+                    }
+                }
+            }
+
+            private async Task FinishAsync()
+            {
+                var subscription = default(IAsyncDisposable);
+
+                lock (_gate)
+                {
+                    if (!_disposing)
+                    {
+                        _disposing = true;
+
+                        subscription = _subscription;
+                    }
+
+                    _task = null;
+                }
+
+                if (subscription != null)
+                {
+                    await subscription.DisposeAsync().ConfigureAwait(false);
+                }
+            }
+        }
+    }
+}

+ 35 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObserver.cs

@@ -0,0 +1,35 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive
+{
+    public class AsyncObserver<T> : AsyncObserverBase<T>
+    {
+        private readonly Func<T, Task> _onNextAsync;
+        private readonly Func<Exception, Task> _onErrorAsync;
+        private readonly Func<Task> _onCompletedAsync;
+
+        public AsyncObserver(Func<T, Task> onNextAsync, Func<Exception, Task> onErrorAsync, Func<Task> onCompletedAsync)
+        {
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onErrorAsync == null)
+                throw new ArgumentNullException(nameof(onErrorAsync));
+            if (onCompletedAsync == null)
+                throw new ArgumentNullException(nameof(onCompletedAsync));
+
+            _onNextAsync = onNextAsync;
+            _onErrorAsync = onErrorAsync;
+            _onCompletedAsync = onCompletedAsync;
+        }
+
+        protected override Task OnCompletedAsyncCore() => _onCompletedAsync();
+
+        protected override Task OnErrorAsyncCore(Exception error) => _onErrorAsync(error ?? throw new ArgumentNullException(nameof(error)));
+
+        protected override Task OnNextAsyncCore(T value) => _onNextAsync(value);
+    }
+}

+ 82 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/AsyncObserverBase.cs

@@ -0,0 +1,82 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive
+{
+    public abstract class AsyncObserverBase<T> : IAsyncObserver<T>
+    {
+        private const int Idle = 0;
+        private const int Busy = 1;
+        private const int Done = 2;
+
+        private int _status = Idle;
+
+        public Task OnCompletedAsync()
+        {
+            TryEnter();
+
+            try
+            {
+                return OnCompletedAsyncCore();
+            }
+            finally
+            {
+                Interlocked.Exchange(ref _status, Done);
+            }
+        }
+
+        protected abstract Task OnCompletedAsyncCore();
+
+        public Task OnErrorAsync(Exception error)
+        {
+            if (error == null)
+                throw new ArgumentNullException(nameof(error));
+
+            TryEnter();
+
+            try
+            {
+                return OnErrorAsyncCore(error);
+            }
+            finally
+            {
+                Interlocked.Exchange(ref _status, Done);
+            }
+        }
+
+        protected abstract Task OnErrorAsyncCore(Exception error);
+
+        public Task OnNextAsync(T value)
+        {
+            TryEnter();
+
+            try
+            {
+                return OnNextAsyncCore(value);
+            }
+            finally
+            {
+                Interlocked.Exchange(ref _status, Idle);
+            }
+        }
+
+        protected abstract Task OnNextAsyncCore(T value);
+
+        private void TryEnter()
+        {
+            var old = Interlocked.CompareExchange(ref _status, Busy, Idle);
+
+            switch (old)
+            {
+                case Busy:
+                    throw new InvalidOperationException("The observer is currently processing a notification.");
+                case Done:
+                    throw new InvalidOperationException("The observer has already terminated.");
+            }
+        }
+    }
+}

+ 28 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/Subjects/AnonymousAsyncSubject.cs

@@ -0,0 +1,28 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Subjects
+{
+    internal sealed class AnonymousAsyncSubject<T> : IAsyncSubject<T>
+    {
+        private readonly IAsyncObserver<T> _observer;
+        private readonly IAsyncObservable<T> _observable;
+
+        public AnonymousAsyncSubject(IAsyncObserver<T> observer, IAsyncObservable<T> observable)
+        {
+            _observer = observer;
+            _observable = observable;
+        }
+
+        public Task OnCompletedAsync() => _observer.OnCompletedAsync();
+
+        public Task OnErrorAsync(Exception error) => _observer.OnErrorAsync(error ?? throw new ArgumentNullException(nameof(error)));
+
+        public Task OnNextAsync(T value) => _observer.OnNextAsync(value);
+
+        public Task<IAsyncDisposable> SubscribeAsync(IAsyncObserver<T> observer) => _observable.SubscribeAsync(observer ?? throw new ArgumentNullException(nameof(observer)));
+    }
+}

+ 19 - 0
AsyncRx.NET/System.Reactive.Async.Core/System/Reactive/Subjects/AsyncSubject.cs

@@ -0,0 +1,19 @@
+// 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. 
+
+namespace System.Reactive.Subjects
+{
+    public static class AsyncSubject
+    {
+        public static IAsyncSubject<T> Create<T>(IAsyncObserver<T> observer, IAsyncObservable<T> observable)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (observable == null)
+                throw new ArgumentNullException(nameof(observable));
+
+            return new AnonymousAsyncSubject<T>(observer, observable);
+        }
+    }
+}

+ 12 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System.Reactive.Async.Disposables.csproj

@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async.Interfaces\System.Reactive.Async.Interfaces.csproj" />
+    <ProjectReference Include="..\System.Reactive.Bcl\System.Reactive.Bcl.csproj" />
+  </ItemGroup>
+
+</Project>

+ 39 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/AsyncDisposable.cs

@@ -0,0 +1,39 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public static class AsyncDisposable
+    {
+        public static IAsyncDisposable Nop { get; } = new NopAsyncDisposable();
+
+        public static IAsyncDisposable Create(Func<Task> dispose)
+        {
+            if (dispose == null)
+                throw new ArgumentNullException(nameof(dispose));
+
+            return new AnonymousAsyncDisposable(dispose);
+        }
+
+        private sealed class AnonymousAsyncDisposable : IAsyncDisposable
+        {
+            private Func<Task> _dispose;
+
+            public AnonymousAsyncDisposable(Func<Task> dispose)
+            {
+                _dispose = dispose;
+            }
+
+            public Task DisposeAsync() => Interlocked.Exchange(ref _dispose, null)?.Invoke() ?? Task.CompletedTask;
+        }
+
+        private sealed class NopAsyncDisposable : IAsyncDisposable
+        {
+            public Task DisposeAsync() => Task.CompletedTask;
+        }
+    }
+}

+ 36 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/CancellationAsyncDisposable.cs

@@ -0,0 +1,36 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public sealed class CancellationAsyncDisposable : IAsyncDisposable
+    {
+        private readonly CancellationTokenSource _cts;
+
+        public CancellationAsyncDisposable()
+            : this(new CancellationTokenSource())
+        {
+        }
+
+        public CancellationAsyncDisposable(CancellationTokenSource cts)
+        {
+            if (cts == null)
+                throw new ArgumentNullException(nameof(cts));
+
+            _cts = cts;
+        }
+
+        public CancellationToken Token => _cts.Token;
+
+        public Task DisposeAsync()
+        {
+            _cts.Cancel();
+
+            return Task.CompletedTask;
+        }
+    }
+}

+ 110 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/CompositeAsyncDisposable.cs

@@ -0,0 +1,110 @@
+// 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.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public sealed class CompositeAsyncDisposable : IAsyncDisposable
+    {
+        private readonly AsyncLock _gate = new AsyncLock();
+        private readonly List<IAsyncDisposable> _disposables;
+        private bool _disposed;
+
+        public CompositeAsyncDisposable()
+        {
+            _disposables = new List<IAsyncDisposable>();
+        }
+
+        public CompositeAsyncDisposable(params IAsyncDisposable[] disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            _disposables = new List<IAsyncDisposable>(disposables);
+        }
+
+        public CompositeAsyncDisposable(IEnumerable<IAsyncDisposable> disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            _disposables = new List<IAsyncDisposable>(disposables);
+        }
+
+        public async Task AddAsync(IAsyncDisposable disposable)
+        {
+            if (disposable == null)
+                throw new ArgumentNullException(nameof(disposable));
+
+            var shouldDispose = false;
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (_disposed)
+                {
+                    shouldDispose = true;
+                }
+                else
+                {
+                    _disposables.Add(disposable);
+                }
+            }
+
+            if (shouldDispose)
+            {
+                await disposable.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        public async Task<bool> RemoveAsync(IAsyncDisposable disposable)
+        {
+            if (disposable == null)
+                throw new ArgumentNullException(nameof(disposable));
+
+            var shouldDispose = false;
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (!_disposed && _disposables.Remove(disposable))
+                {
+                    shouldDispose = true;
+                }
+            }
+
+            if (shouldDispose)
+            {
+                await disposable.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return shouldDispose;
+        }
+
+        public async Task DisposeAsync()
+        {
+            var disposables = default(IAsyncDisposable[]);
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (!_disposed)
+                {
+                    _disposed = true;
+
+                    disposables = _disposables.ToArray();
+                    _disposables.Clear();
+                }
+            }
+
+            if (disposables != null)
+            {
+                var tasks = disposables.Select(disposable => disposable.DisposeAsync());
+
+                await Task.WhenAll(tasks);
+            }
+        }
+    }
+}

+ 103 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/RefCountAsyncDisposable.cs

@@ -0,0 +1,103 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public sealed class RefCountAsyncDisposable : IAsyncDisposable
+    {
+        private readonly AsyncLock _gate = new AsyncLock();
+        private IAsyncDisposable _disposable;
+        private bool _primaryDisposed;
+        private int _count;
+
+        public RefCountAsyncDisposable(IAsyncDisposable disposable)
+        {
+            if (disposable == null)
+                throw new ArgumentNullException(nameof(disposable));
+
+            _disposable = disposable;
+            _primaryDisposed = false;
+            _count = 0;
+        }
+
+        public async Task<IAsyncDisposable> GetDisposableAsync()
+        {
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (_disposable == null)
+                {
+                    return AsyncDisposable.Nop;
+                }
+                else
+                {
+                    _count++;
+                    return new Inner(this);
+                }
+            }
+        }
+
+        public async Task DisposeAsync()
+        {
+            var disposable = default(IAsyncDisposable);
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (_disposable != null && !_primaryDisposed)
+                {
+                    _primaryDisposed = true;
+
+                    if (_count == 0)
+                    {
+                        disposable = _disposable;
+                        _disposable = null;
+                    }
+                }
+            }
+
+            if (disposable != null)
+            {
+                await disposable.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private async Task ReleaseAsync()
+        {
+            var disposable = default(IAsyncDisposable);
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (_disposable != null)
+                {
+                    _count--;
+
+                    if (_primaryDisposed && _count == 0)
+                    {
+                        disposable = _disposable;
+                        _disposable = null;
+                    }
+                }
+            }
+
+            if (disposable != null)
+            {
+                await disposable.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private sealed class Inner : IAsyncDisposable
+        {
+            private RefCountAsyncDisposable _parent;
+
+            public Inner(RefCountAsyncDisposable parent)
+            {
+                _parent = parent;
+            }
+
+            public Task DisposeAsync() => Interlocked.Exchange(ref _parent, null)?.ReleaseAsync() ?? Task.CompletedTask;
+        }
+    }
+}

+ 69 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/SerialAsyncDisposable.cs

@@ -0,0 +1,69 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public sealed class SerialAsyncDisposable : IAsyncDisposable
+    {
+        private readonly AsyncLock _gate = new AsyncLock();
+
+        private IAsyncDisposable _disposable;
+        private bool _disposed;
+
+        public async Task AssignAsync(IAsyncDisposable disposable)
+        {
+            if (disposable == null)
+                throw new ArgumentNullException(nameof(disposable));
+
+            var shouldDispose = false;
+            var old = default(IAsyncDisposable);
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (_disposed)
+                {
+                    shouldDispose = true;
+                }
+                else
+                {
+                    old = _disposable;
+                    _disposable = disposable;
+                }
+            }
+
+            if (old != null)
+            {
+                await old.DisposeAsync().ConfigureAwait(false);
+            }
+
+            if (shouldDispose && disposable != null)
+            {
+                await disposable.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        public async Task DisposeAsync()
+        {
+            var old = default(IAsyncDisposable);
+
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (!_disposed)
+                {
+                    _disposed = true;
+                    old = _disposable;
+                    _disposable = null;
+                }
+            }
+
+            if (old != null)
+            {
+                await old.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+    }
+}

+ 37 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/SingleAssignmentAsyncDisposable.cs

@@ -0,0 +1,37 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public sealed class SingleAssignmentAsyncDisposable : IAsyncDisposable
+    {
+        private static readonly IAsyncDisposable Disposed = AsyncDisposable.Create(() => Task.CompletedTask);
+
+        private IAsyncDisposable _disposable;
+
+        public async Task AssignAsync(IAsyncDisposable disposable)
+        {
+            if (disposable == null)
+                throw new ArgumentNullException(nameof(disposable));
+
+            var old = Interlocked.CompareExchange(ref _disposable, disposable, null);
+
+            if (old == null)
+                return;
+
+            if (old != Disposed)
+                throw new InvalidOperationException("Disposable already assigned.");
+
+            await disposable.DisposeAsync().ConfigureAwait(false);
+        }
+
+        public Task DisposeAsync()
+        {
+            return Interlocked.Exchange(ref _disposable, Disposed)?.DisposeAsync() ?? Task.CompletedTask;
+        }
+    }
+}

+ 98 - 0
AsyncRx.NET/System.Reactive.Async.Disposables/System/Reactive/Disposables/StableCompositeAsyncDisposable.cs

@@ -0,0 +1,98 @@
+// 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.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Disposables
+{
+    public abstract class StableCompositeAsyncDisposable : IAsyncDisposable
+    {
+        public static StableCompositeAsyncDisposable Create(IAsyncDisposable disposable1, IAsyncDisposable disposable2)
+        {
+            if (disposable1 == null)
+                throw new ArgumentNullException(nameof(disposable1));
+            if (disposable2 == null)
+                throw new ArgumentNullException(nameof(disposable2));
+
+            return new Binary(disposable1, disposable2);
+        }
+
+        public static StableCompositeAsyncDisposable Create(params IAsyncDisposable[] disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            return new NAry(disposables);
+        }
+
+        public static StableCompositeAsyncDisposable Create(IEnumerable<IAsyncDisposable> disposables)
+        {
+            if (disposables == null)
+                throw new ArgumentNullException(nameof(disposables));
+
+            return new NAry(disposables);
+        }
+
+        public abstract Task DisposeAsync();
+
+        private sealed class Binary : StableCompositeAsyncDisposable
+        {
+            private volatile IAsyncDisposable _disposable1;
+            private volatile IAsyncDisposable _disposable2;
+
+            public Binary(IAsyncDisposable disposable1, IAsyncDisposable disposable2)
+            {
+                _disposable1 = disposable1;
+                _disposable2 = disposable2;
+            }
+
+            public override async Task DisposeAsync()
+            {
+                var d1 = Interlocked.Exchange(ref _disposable1, null);
+                if (d1 != null)
+                {
+                    await d1.DisposeAsync().ConfigureAwait(false);
+                }
+
+                var d2 = Interlocked.Exchange(ref _disposable2, null);
+                if (d2 != null)
+                {
+                    await d2.DisposeAsync().ConfigureAwait(false);
+                }
+            }
+        }
+
+        private sealed class NAry : StableCompositeAsyncDisposable
+        {
+            private volatile List<IAsyncDisposable> _disposables;
+
+            public NAry(IAsyncDisposable[] disposables)
+                : this((IEnumerable<IAsyncDisposable>)disposables)
+            {
+            }
+
+            public NAry(IEnumerable<IAsyncDisposable> disposables)
+            {
+                _disposables = new List<IAsyncDisposable>(disposables);
+            }
+
+            public override async Task DisposeAsync()
+            {
+                var old = Interlocked.Exchange(ref _disposables, null);
+                if (old != null)
+                {
+                    foreach (var d in old)
+                    {
+                        if (d != null)
+                        {
+                            await d.DisposeAsync().ConfigureAwait(false);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 7 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System.Reactive.Async.Interfaces.csproj

@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+</Project>

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncDisposable.cs

@@ -0,0 +1,13 @@
+// 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.Threading.Tasks;
+
+namespace System
+{
+    public interface IAsyncDisposable
+    {
+        Task DisposeAsync();
+    }
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncObservable.cs

@@ -0,0 +1,13 @@
+// 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.Threading.Tasks;
+
+namespace System
+{
+    public interface IAsyncObservable<out T>
+    {
+        Task<IAsyncDisposable> SubscribeAsync(IAsyncObserver<T> observer);
+    }
+}

+ 15 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/IAsyncObserver.cs

@@ -0,0 +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.Threading.Tasks;
+
+namespace System
+{
+    public interface IAsyncObserver<in T>
+    {
+        Task OnNextAsync(T value);
+        Task OnErrorAsync(Exception error);
+        Task OnCompletedAsync();
+    }
+}

+ 16 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Concurrency/IAsyncScheduler.cs

@@ -0,0 +1,16 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Concurrency
+{
+    public interface IAsyncScheduler : IClock
+    {
+        Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action);
+        Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action, TimeSpan dueTime);
+        Task<IAsyncDisposable> ScheduleAsync(Func<CancellationToken, Task> action, DateTimeOffset dueTime);
+    }
+}

+ 11 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Concurrency/IClock.cs

@@ -0,0 +1,11 @@
+// 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. 
+
+namespace System.Reactive.Concurrency
+{
+    public interface IClock
+    {
+        DateTimeOffset Now { get; }
+    }
+}

+ 11 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Linq/IGroupedAsyncObservable.cs

@@ -0,0 +1,11 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    public interface IGroupedAsyncObservable<out TKey, out TElement> : IAsyncObservable<TElement>
+    {
+        TKey Key { get; }
+    }
+}

+ 14 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Subjects/IAsyncSubject.cs

@@ -0,0 +1,14 @@
+// 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. 
+
+namespace System.Reactive.Subjects
+{
+    public interface IAsyncSubject<in TInput, out TOutput> : IAsyncObservable<TOutput>, IAsyncObserver<TInput>
+    {
+    }
+
+    public interface IAsyncSubject<T> : IAsyncSubject<T, T>
+    {
+    }
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Interfaces/System/Reactive/Subjects/IConnectableAsyncObservable.cs

@@ -0,0 +1,13 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Subjects
+{
+    public interface IConnectableAsyncObservable<out T> : IAsyncObservable<T>
+    {
+        Task<IAsyncDisposable> ConnectAsync();
+    }
+}

+ 143 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System.Reactive.Async.Linq.csproj

@@ -0,0 +1,143 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Include="System\Reactive\Linq\Operators\FromEvent.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>FromEvent.Generated.tt</DependentUpon>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\System.Reactive.Async.Concurrency\System.Reactive.Async.Concurrency.csproj" />
+    <ProjectReference Include="..\System.Reactive.Async.Core\System.Reactive.Async.Core.csproj" />
+    <ProjectReference Include="..\System.Reactive.Async.Disposables\System.Reactive.Async.Disposables.csproj" />
+    <ProjectReference Include="..\System.Reactive.Async.Interfaces\System.Reactive.Async.Interfaces.csproj" />
+    <ProjectReference Include="..\System.Reactive.Async.Subjects\System.Reactive.Async.Subjects.csproj" />
+    <ProjectReference Include="..\System.Reactive.Bcl\System.Reactive.Bcl.csproj" />
+    <ProjectReference Include="..\System.Reactive.Shared\System.Reactive.Shared.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="System\Reactive\Joins\ActiveAsyncPlan.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>ActiveAsyncPlan.Generated.tt</DependentUpon>
+    </Compile>
+    <Compile Update="System\Reactive\Joins\AsyncPattern.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>AsyncPattern.Generated.tt</DependentUpon>
+    </Compile>
+    <Compile Update="System\Reactive\Joins\AsyncPlan.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>AsyncPlan.Generated.tt</DependentUpon>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\Average.Generated.cs">
+      <DependentUpon>Average.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\CombineLatest.Generated.cs">
+      <DependentUpon>CombineLatest.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\FromAsyncPattern.Generated.cs">
+      <DependentUpon>FromAsyncPattern.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\FromEvent.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>FromEvent.Generated.tt</DependentUpon>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\Max.Generated.cs">
+      <DependentUpon>Max.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\Min.Generated.cs">
+      <DependentUpon>Min.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\Sum.Generated.cs">
+      <DependentUpon>Sum.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\ToAsync.Generated.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>ToAsync.Generated.tt</DependentUpon>
+    </Compile>
+    <Compile Update="System\Reactive\Linq\Operators\Zip.Generated.cs">
+      <DependentUpon>Zip.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="System\Reactive\Joins\ActiveAsyncPlan.Generated.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>ActiveAsyncPlan.Generated.cs</LastGenOutput>
+    </None>
+    <None Update="System\Reactive\Joins\AsyncPattern.Generated.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>AsyncPattern.Generated.cs</LastGenOutput>
+    </None>
+    <None Update="System\Reactive\Joins\AsyncPlan.Generated.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>AsyncPlan.Generated.cs</LastGenOutput>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\Average.Generated.tt">
+      <LastGenOutput>Average.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\CombineLatest.Generated.tt">
+      <LastGenOutput>CombineLatest.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\FromEvent.Generated.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>FromEvent.Generated.cs</LastGenOutput>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\ToAsync.Generated.tt">
+      <LastGenOutput>ToAsync.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\FromAsyncPattern.Generated.tt">
+      <LastGenOutput>FromAsyncPattern.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\Max.Generated.tt">
+      <LastGenOutput>Max.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\Min.Generated.tt">
+      <LastGenOutput>Min.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\Sum.Generated.tt">
+      <LastGenOutput>Sum.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+    <None Update="System\Reactive\Linq\Operators\Zip.Generated.tt">
+      <LastGenOutput>Zip.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
+
+</Project>

+ 26 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/AsyncQueueLockAsyncObserver.cs

@@ -0,0 +1,26 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive
+{
+    internal sealed class AsyncQueueLockAsyncObserver<T> : AsyncObserverBase<T>
+    {
+        private readonly AsyncQueueLock _gate = new AsyncQueueLock();
+        private readonly IAsyncObserver<T> _observer;
+
+        public AsyncQueueLockAsyncObserver(IAsyncObserver<T> observer)
+        {
+            _observer = observer;
+        }
+
+        protected override Task OnCompletedAsyncCore() => _gate.WaitAsync(_observer.OnCompletedAsync);
+
+        protected override Task OnErrorAsyncCore(Exception error) => _gate.WaitAsync(() => _observer.OnErrorAsync(error));
+
+        protected override Task OnNextAsyncCore(T value) => _gate.WaitAsync(() => _observer.OnNextAsync(value));
+    }
+}

+ 27 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventPatternSource.cs

@@ -0,0 +1,27 @@
+// 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. 
+
+namespace System.Reactive
+{
+    internal sealed class EventPatternSource<TEventArgs> : EventPatternSourceBase<object, TEventArgs>, IEventPatternSource<TEventArgs>
+    {
+        public EventPatternSource(IAsyncObservable<EventPattern<object, TEventArgs>> source, Action<Action<object, TEventArgs>, /*object,*/ EventPattern<object, TEventArgs>> invokeHandler)
+            : base(source, invokeHandler)
+        {
+        }
+
+        event EventHandler<TEventArgs> IEventPatternSource<TEventArgs>.OnNext
+        {
+            add
+            {
+                Add(value, (o, e) => value(o, e));
+            }
+
+            remove
+            {
+                Remove(value);
+            }
+        }
+    }
+}

+ 126 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventPatternSourceBase.cs

@@ -0,0 +1,126 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive
+{
+    /// <summary>
+    /// Base class for classes that expose an observable sequence as a well-known event pattern (sender, event arguments).
+    /// Contains functionality to maintain a map of event handler delegates to observable sequence subscriptions. Subclasses
+    /// should only add an event with custom add and remove methods calling into the base class's operations.
+    /// </summary>
+    /// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
+    /// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
+    internal abstract class EventPatternSourceBase<TSender, TEventArgs>
+    {
+        private readonly IAsyncObservable<EventPattern<TSender, TEventArgs>> _source;
+        private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;
+        private readonly Action<Action<TSender, TEventArgs>, /*object,*/ EventPattern<TSender, TEventArgs>> _invokeHandler;
+
+        /// <summary>
+        /// Creates a new event pattern source.
+        /// </summary>
+        /// <param name="source">Source sequence to expose as an event.</param>
+        /// <param name="invokeHandler">Delegate used to invoke the event for each element of the sequence.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="invokeHandler"/> is null.</exception>
+        protected EventPatternSourceBase(IAsyncObservable<EventPattern<TSender, TEventArgs>> source, Action<Action<TSender, TEventArgs>, /*object,*/ EventPattern<TSender, TEventArgs>> invokeHandler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (invokeHandler == null)
+                throw new ArgumentNullException(nameof(invokeHandler));
+
+            _source = source;
+            _invokeHandler = invokeHandler;
+            _subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
+        }
+
+        /// <summary>
+        /// Adds the specified event handler, causing a subscription to the underlying source.
+        /// </summary>
+        /// <param name="handler">Event handler to add. The same delegate should be passed to the Remove operation in order to remove the event handler.</param>
+        /// <param name="invoke">Invocation delegate to raise the event in the derived class.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="handler"/> or <paramref name="invoke"/> is null.</exception>
+        protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke)
+        {
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+            if (invoke == null)
+                throw new ArgumentNullException(nameof(invoke));
+
+            var gate = new object();
+            var isAdded = false;
+            var isDone = false;
+
+            var remove = new Action(() =>
+            {
+                lock (gate)
+                {
+                    if (isAdded)
+                        Remove(handler);
+                    else
+                        isDone = true;
+                }
+            });
+
+            //
+            // [OK] Use of unsafe SubscribeAsync: non-pretentious wrapper of an observable in an event; exceptions can occur during +=.
+            //
+            var d = _source.SubscribeAsync(
+                x => { _invokeHandler(invoke, /*this,*/ x); return Task.CompletedTask; },
+                ex => { remove(); return Task.FromException(ex); },
+                () => { remove(); return Task.CompletedTask; }
+            );
+
+            lock (gate)
+            {
+                if (!isDone)
+                {
+                    Add(handler, d);
+                    isAdded = true;
+                }
+            }
+        }
+
+        private void Add(Delegate handler, IDisposable disposable)
+        {
+            lock (_subscriptions)
+            {
+                var l = new Stack<IDisposable>();
+                if (!_subscriptions.TryGetValue(handler, out l))
+                    _subscriptions[handler] = l = new Stack<IDisposable>();
+
+                l.Push(disposable);
+            }
+        }
+
+        /// <summary>
+        /// Removes the specified event handler, causing a disposal of the corresponding subscription to the underlying source that was created during the Add operation.
+        /// </summary>
+        /// <param name="handler">Event handler to remove. This should be the same delegate as one that was passed to the Add operation.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="handler"/> is null.</exception>
+        protected void Remove(Delegate handler)
+        {
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            var d = default(IDisposable);
+
+            lock (_subscriptions)
+            {
+                var l = new Stack<IDisposable>();
+                if (_subscriptions.TryGetValue(handler, out l))
+                {
+                    d = l.Pop();
+                    if (l.Count == 0)
+                        _subscriptions.Remove(handler);
+                }
+            }
+
+            d?.Dispose();
+        }
+    }
+}

+ 97 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/EventSource.cs

@@ -0,0 +1,97 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive
+{
+    internal sealed class EventSource<T> : IEventSource<T>
+    {
+        private readonly IAsyncObservable<T> _source;
+        private readonly Dictionary<Delegate, Stack<IDisposable>> _subscriptions;
+        private readonly Action<Action<T>, /*object,*/ T> _invokeHandler;
+
+        public EventSource(IAsyncObservable<T> source, Action<Action<T>, /*object,*/ T> invokeHandler)
+        {
+            _source = source;
+            _invokeHandler = invokeHandler;
+            _subscriptions = new Dictionary<Delegate, Stack<IDisposable>>();
+        }
+
+        public event Action<T> OnNext
+        {
+            add
+            {
+                var gate = new object();
+                var isAdded = false;
+                var isDone = false;
+
+                var remove = new Action(() =>
+                {
+                    lock (gate)
+                    {
+                        if (isAdded)
+                            Remove(value);
+                        else
+                            isDone = true;
+                    }
+                });
+
+                //
+                // [OK] Use of unsafe SubscribeAsync: non-pretentious wrapper of an observable in an event; exceptions can occur during +=.
+                //
+                var d = _source.SubscribeAsync(
+                    x => { _invokeHandler(value, /*this,*/ x); return Task.CompletedTask; },
+                    ex => { remove(); return Task.FromException(ex); },
+                    () => { remove(); return Task.CompletedTask; }
+                );
+
+                lock (gate)
+                {
+                    if (!isDone)
+                    {
+                        Add(value, d);
+                        isAdded = true;
+                    }
+                }
+            }
+
+            remove
+            {
+                Remove(value);
+            }
+        }
+
+        private void Add(Delegate handler, IDisposable disposable)
+        {
+            lock (_subscriptions)
+            {
+                var l = new Stack<IDisposable>();
+                if (!_subscriptions.TryGetValue(handler, out l))
+                    _subscriptions[handler] = l = new Stack<IDisposable>();
+
+                l.Push(disposable);
+            }
+        }
+
+        private void Remove(Delegate handler)
+        {
+            var d = default(IDisposable);
+
+            lock (_subscriptions)
+            {
+                var l = new Stack<IDisposable>();
+                if (_subscriptions.TryGetValue(handler, out l))
+                {
+                    d = l.Pop();
+                    if (l.Count == 0)
+                        _subscriptions.Remove(handler);
+                }
+            }
+
+            d?.Dispose();
+        }
+    }
+}

+ 73 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Internal/Lookup.cs

@@ -0,0 +1,73 @@
+// 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.Linq;
+
+namespace System.Reactive
+{
+    internal sealed class Lookup<K, E> : ILookup<K, E>
+    {
+        private readonly Dictionary<K, List<E>> d;
+
+        public Lookup(IEqualityComparer<K> comparer)
+        {
+            d = new Dictionary<K, List<E>>(comparer);
+        }
+
+        public void Add(K key, E element)
+        {
+            if (!d.TryGetValue(key, out var list))
+                d[key] = list = new List<E>();
+
+            list.Add(element);
+        }
+
+        public bool Contains(K key) => d.ContainsKey(key);
+
+        public int Count => d.Count;
+
+        public IEnumerable<E> this[K key]
+        {
+            get
+            {
+                if (!d.TryGetValue(key, out var list))
+                    return Enumerable.Empty<E>();
+
+                return Hide(list);
+            }
+        }
+
+        private IEnumerable<E> Hide(List<E> elements)
+        {
+            foreach (var x in elements)
+                yield return x;
+        }
+
+        public IEnumerator<IGrouping<K, E>> GetEnumerator()
+        {
+            foreach (var kv in d)
+                yield return new Grouping(kv);
+        }
+
+        private sealed class Grouping : IGrouping<K, E>
+        {
+            private readonly KeyValuePair<K, List<E>> kv;
+
+            public Grouping(KeyValuePair<K, List<E>> kv)
+            {
+                this.kv = kv;
+            }
+
+            public K Key => kv.Key;
+
+            public IEnumerator<E> GetEnumerator() => kv.Value.GetEnumerator();
+
+            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+    }
+}

+ 1081 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.Generated.cs

@@ -0,0 +1,1081 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    internal sealed class ActiveAsyncPlan<TSource1> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, Func<TSource1, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+
+            AddJoinObserver(observer1);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, Func<TSource1, TSource2, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, Func<TSource1, TSource2, TSource3, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, Func<TSource1, TSource2, TSource3, TSource4, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, Func<TSource1, TSource2, TSource3, TSource4, TSource5, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+        private readonly AsyncJoinObserver<TSource12> _observer12;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, AsyncJoinObserver<TSource12> observer12, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+            _observer12 = observer12;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+            AddJoinObserver(observer12);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0 && _observer12.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+                var notification12 = _observer12.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted || notification12.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value, notification12.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+        private readonly AsyncJoinObserver<TSource12> _observer12;
+        private readonly AsyncJoinObserver<TSource13> _observer13;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, AsyncJoinObserver<TSource12> observer12, AsyncJoinObserver<TSource13> observer13, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+            _observer12 = observer12;
+            _observer13 = observer13;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+            AddJoinObserver(observer12);
+            AddJoinObserver(observer13);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0 && _observer12.Queue.Count > 0 && _observer13.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+                var notification12 = _observer12.Queue.Peek();
+                var notification13 = _observer13.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted || notification12.Kind == NotificationKind.OnCompleted || notification13.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value, notification12.Value, notification13.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+        private readonly AsyncJoinObserver<TSource12> _observer12;
+        private readonly AsyncJoinObserver<TSource13> _observer13;
+        private readonly AsyncJoinObserver<TSource14> _observer14;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, AsyncJoinObserver<TSource12> observer12, AsyncJoinObserver<TSource13> observer13, AsyncJoinObserver<TSource14> observer14, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+            _observer12 = observer12;
+            _observer13 = observer13;
+            _observer14 = observer14;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+            AddJoinObserver(observer12);
+            AddJoinObserver(observer13);
+            AddJoinObserver(observer14);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0 && _observer12.Queue.Count > 0 && _observer13.Queue.Count > 0 && _observer14.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+                var notification12 = _observer12.Queue.Peek();
+                var notification13 = _observer13.Queue.Peek();
+                var notification14 = _observer14.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted || notification12.Kind == NotificationKind.OnCompleted || notification13.Kind == NotificationKind.OnCompleted || notification14.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value, notification12.Value, notification13.Value, notification14.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+        private readonly AsyncJoinObserver<TSource12> _observer12;
+        private readonly AsyncJoinObserver<TSource13> _observer13;
+        private readonly AsyncJoinObserver<TSource14> _observer14;
+        private readonly AsyncJoinObserver<TSource15> _observer15;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, AsyncJoinObserver<TSource12> observer12, AsyncJoinObserver<TSource13> observer13, AsyncJoinObserver<TSource14> observer14, AsyncJoinObserver<TSource15> observer15, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+            _observer12 = observer12;
+            _observer13 = observer13;
+            _observer14 = observer14;
+            _observer15 = observer15;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+            AddJoinObserver(observer12);
+            AddJoinObserver(observer13);
+            AddJoinObserver(observer14);
+            AddJoinObserver(observer15);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0 && _observer12.Queue.Count > 0 && _observer13.Queue.Count > 0 && _observer14.Queue.Count > 0 && _observer15.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+                var notification12 = _observer12.Queue.Peek();
+                var notification13 = _observer13.Queue.Peek();
+                var notification14 = _observer14.Queue.Peek();
+                var notification15 = _observer15.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted || notification12.Kind == NotificationKind.OnCompleted || notification13.Kind == NotificationKind.OnCompleted || notification14.Kind == NotificationKind.OnCompleted || notification15.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value, notification12.Value, notification13.Value, notification14.Value, notification15.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+    internal sealed class ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> : ActiveAsyncPlan
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+        private readonly AsyncJoinObserver<TSource1> _observer1;
+        private readonly AsyncJoinObserver<TSource2> _observer2;
+        private readonly AsyncJoinObserver<TSource3> _observer3;
+        private readonly AsyncJoinObserver<TSource4> _observer4;
+        private readonly AsyncJoinObserver<TSource5> _observer5;
+        private readonly AsyncJoinObserver<TSource6> _observer6;
+        private readonly AsyncJoinObserver<TSource7> _observer7;
+        private readonly AsyncJoinObserver<TSource8> _observer8;
+        private readonly AsyncJoinObserver<TSource9> _observer9;
+        private readonly AsyncJoinObserver<TSource10> _observer10;
+        private readonly AsyncJoinObserver<TSource11> _observer11;
+        private readonly AsyncJoinObserver<TSource12> _observer12;
+        private readonly AsyncJoinObserver<TSource13> _observer13;
+        private readonly AsyncJoinObserver<TSource14> _observer14;
+        private readonly AsyncJoinObserver<TSource15> _observer15;
+        private readonly AsyncJoinObserver<TSource16> _observer16;
+
+        internal ActiveAsyncPlan(AsyncJoinObserver<TSource1> observer1, AsyncJoinObserver<TSource2> observer2, AsyncJoinObserver<TSource3> observer3, AsyncJoinObserver<TSource4> observer4, AsyncJoinObserver<TSource5> observer5, AsyncJoinObserver<TSource6> observer6, AsyncJoinObserver<TSource7> observer7, AsyncJoinObserver<TSource8> observer8, AsyncJoinObserver<TSource9> observer9, AsyncJoinObserver<TSource10> observer10, AsyncJoinObserver<TSource11> observer11, AsyncJoinObserver<TSource12> observer12, AsyncJoinObserver<TSource13> observer13, AsyncJoinObserver<TSource14> observer14, AsyncJoinObserver<TSource15> observer15, AsyncJoinObserver<TSource16> observer16, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+            _observer1 = observer1;
+            _observer2 = observer2;
+            _observer3 = observer3;
+            _observer4 = observer4;
+            _observer5 = observer5;
+            _observer6 = observer6;
+            _observer7 = observer7;
+            _observer8 = observer8;
+            _observer9 = observer9;
+            _observer10 = observer10;
+            _observer11 = observer11;
+            _observer12 = observer12;
+            _observer13 = observer13;
+            _observer14 = observer14;
+            _observer15 = observer15;
+            _observer16 = observer16;
+
+            AddJoinObserver(observer1);
+            AddJoinObserver(observer2);
+            AddJoinObserver(observer3);
+            AddJoinObserver(observer4);
+            AddJoinObserver(observer5);
+            AddJoinObserver(observer6);
+            AddJoinObserver(observer7);
+            AddJoinObserver(observer8);
+            AddJoinObserver(observer9);
+            AddJoinObserver(observer10);
+            AddJoinObserver(observer11);
+            AddJoinObserver(observer12);
+            AddJoinObserver(observer13);
+            AddJoinObserver(observer14);
+            AddJoinObserver(observer15);
+            AddJoinObserver(observer16);
+        }
+
+        internal override Task Match()
+        {
+            if (_observer1.Queue.Count > 0 && _observer2.Queue.Count > 0 && _observer3.Queue.Count > 0 && _observer4.Queue.Count > 0 && _observer5.Queue.Count > 0 && _observer6.Queue.Count > 0 && _observer7.Queue.Count > 0 && _observer8.Queue.Count > 0 && _observer9.Queue.Count > 0 && _observer10.Queue.Count > 0 && _observer11.Queue.Count > 0 && _observer12.Queue.Count > 0 && _observer13.Queue.Count > 0 && _observer14.Queue.Count > 0 && _observer15.Queue.Count > 0 && _observer16.Queue.Count > 0)
+            {
+                var notification1 = _observer1.Queue.Peek();
+                var notification2 = _observer2.Queue.Peek();
+                var notification3 = _observer3.Queue.Peek();
+                var notification4 = _observer4.Queue.Peek();
+                var notification5 = _observer5.Queue.Peek();
+                var notification6 = _observer6.Queue.Peek();
+                var notification7 = _observer7.Queue.Peek();
+                var notification8 = _observer8.Queue.Peek();
+                var notification9 = _observer9.Queue.Peek();
+                var notification10 = _observer10.Queue.Peek();
+                var notification11 = _observer11.Queue.Peek();
+                var notification12 = _observer12.Queue.Peek();
+                var notification13 = _observer13.Queue.Peek();
+                var notification14 = _observer14.Queue.Peek();
+                var notification15 = _observer15.Queue.Peek();
+                var notification16 = _observer16.Queue.Peek();
+
+                if (notification1.Kind == NotificationKind.OnCompleted || notification2.Kind == NotificationKind.OnCompleted || notification3.Kind == NotificationKind.OnCompleted || notification4.Kind == NotificationKind.OnCompleted || notification5.Kind == NotificationKind.OnCompleted || notification6.Kind == NotificationKind.OnCompleted || notification7.Kind == NotificationKind.OnCompleted || notification8.Kind == NotificationKind.OnCompleted || notification9.Kind == NotificationKind.OnCompleted || notification10.Kind == NotificationKind.OnCompleted || notification11.Kind == NotificationKind.OnCompleted || notification12.Kind == NotificationKind.OnCompleted || notification13.Kind == NotificationKind.OnCompleted || notification14.Kind == NotificationKind.OnCompleted || notification15.Kind == NotificationKind.OnCompleted || notification16.Kind == NotificationKind.OnCompleted)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(notification1.Value, notification2.Value, notification3.Value, notification4.Value, notification5.Value, notification6.Value, notification7.Value, notification8.Value, notification9.Value, notification10.Value, notification11.Value, notification12.Value, notification13.Value, notification14.Value, notification15.Value, notification16.Value);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+}

+ 90 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.Generated.tt

@@ -0,0 +1,90 @@
+// 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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+<#
+for (var i = 1; i <= 16; i++)
+{
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "TSource" + j));
+    var args = string.Join(", ", Enumerable.Range(1, i).Select(j => "IAsyncObservable<TSource" + j + "> source" + j));
+    var observers = string.Join(", ", Enumerable.Range(1, i).Select(j => "AsyncJoinObserver<TSource" + j + "> observer" + j));
+#>
+    internal sealed class ActiveAsyncPlan<<#=genArgs#>> : ActiveAsyncPlan
+    {
+        private readonly Func<<#=genArgs#>, Task> _onNext;
+        private readonly Func<Task> _onCompleted;
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+        private readonly AsyncJoinObserver<TSource<#=j#>> _observer<#=j#>;
+<#
+}
+#>
+
+        internal ActiveAsyncPlan(<#=observers#>, Func<<#=genArgs#>, Task> onNext, Func<Task> onCompleted)
+        {
+            _onNext = onNext;
+            _onCompleted = onCompleted;
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            _observer<#=j#> = observer<#=j#>;
+<#
+}
+#>
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            AddJoinObserver(observer<#=j#>);
+<#
+}
+#>
+        }
+
+        internal override Task Match()
+        {
+            if (<#=string.Join(" && ", Enumerable.Range(1, i).Select(j => "_observer" + j + ".Queue.Count > 0"))#>)
+            {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                var notification<#=j#> = _observer<#=j#>.Queue.Peek();
+<#
+}
+#>
+
+                if (<#=string.Join(" || ", Enumerable.Range(1, i).Select(j => "notification" + j + ".Kind == NotificationKind.OnCompleted"))#>)
+                {
+                    return _onCompleted();
+                }
+
+                Dequeue();
+
+                return _onNext(<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "notification" + j + ".Value"))#>);
+            }
+
+            return Task.CompletedTask;
+        }
+    }
+
+<#
+}
+#>
+}

+ 29 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/ActiveAsyncPlan.cs

@@ -0,0 +1,29 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    internal abstract class ActiveAsyncPlan
+    {
+        private readonly Dictionary<IAsyncJoinObserver, IAsyncJoinObserver> joinObservers = new Dictionary<IAsyncJoinObserver, IAsyncJoinObserver>();
+
+        internal abstract Task Match();
+
+        protected void AddJoinObserver(IAsyncJoinObserver joinObserver)
+        {
+            joinObservers.Add(joinObserver, joinObserver);
+        }
+
+        protected void Dequeue()
+        {
+            foreach (var observer in joinObservers.Values)
+            {
+                observer.Dequeue();
+            }
+        }
+    }
+}

+ 96 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncJoinObserver.cs

@@ -0,0 +1,96 @@
+// 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.Generic;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    internal sealed class AsyncJoinObserver<T> : AsyncObserverBase<Notification<T>>, IAsyncJoinObserver
+    {
+        private readonly IAsyncObservable<T> _source;
+        private readonly Func<Exception, Task> _onError;
+
+        private readonly List<ActiveAsyncPlan> _activePlans = new List<ActiveAsyncPlan>();
+        private readonly SingleAssignmentAsyncDisposable _subscription = new SingleAssignmentAsyncDisposable();
+
+        private AsyncLock _gate;
+        private bool _isDisposed;
+
+        public AsyncJoinObserver(IAsyncObservable<T> source, Func<Exception, Task> onError)
+        {
+            _source = source;
+            _onError = onError;
+        }
+
+        public Queue<Notification<T>> Queue { get; } = new Queue<Notification<T>>();
+
+        public void Dequeue() => Queue.Dequeue();
+
+        public void AddActivePlan(ActiveAsyncPlan activePlan)
+        {
+            _activePlans.Add(activePlan);
+        }
+
+        internal async Task RemoveActivePlan(ActiveAsyncPlan activePlan)
+        {
+            _activePlans.Remove(activePlan);
+
+            if (_activePlans.Count == 0)
+            {
+                await DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        public async Task DisposeAsync()
+        {
+            if (!_isDisposed)
+            {
+                await _subscription.DisposeAsync().ConfigureAwait(false);
+
+                _isDisposed = true;
+            }
+        }
+
+        public async Task SubscribeAsync(AsyncLock gate)
+        {
+            _gate = gate;
+
+            var d = await _source.Materialize().SubscribeSafeAsync(this).ConfigureAwait(false);
+            await _subscription.AssignAsync(d).ConfigureAwait(false);
+        }
+
+        protected override Task OnCompletedAsyncCore() => Task.CompletedTask;
+
+        protected override Task OnErrorAsyncCore(Exception error) => Task.CompletedTask;
+
+        protected override async Task OnNextAsyncCore(Notification<T> notification)
+        {
+            using (await _gate.LockAsync().ConfigureAwait(false))
+            {
+                if (!_isDisposed)
+                {
+                    if (notification.Kind == NotificationKind.OnError)
+                    {
+                        await _onError(notification.Exception).ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        Queue.Enqueue(notification);
+
+                        var plans = _activePlans.ToArray();
+
+                        for (var i = 0; i < plans.Length; i++)
+                        {
+                            await plans[i].Match().ConfigureAwait(false); // REVIEW: Consider concurrent matching.
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 665 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.Generated.cs

@@ -0,0 +1,665 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    public class AsyncPattern<TSource1> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1)
+        {
+            Source1 = source1;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2)
+        {
+            Source1 = source1;
+            Source2 = source2;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+        internal IAsyncObservable<TSource12> Source12 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11, IAsyncObservable<TSource12> source12)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+            Source12 = source12;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+        internal IAsyncObservable<TSource12> Source12 { get; }
+        internal IAsyncObservable<TSource13> Source13 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11, IAsyncObservable<TSource12> source12, IAsyncObservable<TSource13> source13)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+            Source12 = source12;
+            Source13 = source13;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+        internal IAsyncObservable<TSource12> Source12 { get; }
+        internal IAsyncObservable<TSource13> Source13 { get; }
+        internal IAsyncObservable<TSource14> Source14 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11, IAsyncObservable<TSource12> source12, IAsyncObservable<TSource13> source13, IAsyncObservable<TSource14> source14)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+            Source12 = source12;
+            Source13 = source13;
+            Source14 = source14;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+        internal IAsyncObservable<TSource12> Source12 { get; }
+        internal IAsyncObservable<TSource13> Source13 { get; }
+        internal IAsyncObservable<TSource14> Source14 { get; }
+        internal IAsyncObservable<TSource15> Source15 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11, IAsyncObservable<TSource12> source12, IAsyncObservable<TSource13> source13, IAsyncObservable<TSource14> source14, IAsyncObservable<TSource15> source15)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+            Source12 = source12;
+            Source13 = source13;
+            Source14 = source14;
+            Source15 = source15;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult>(this, selector);
+        }
+    }
+
+    public class AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> : AsyncPattern
+    {
+        internal IAsyncObservable<TSource1> Source1 { get; }
+        internal IAsyncObservable<TSource2> Source2 { get; }
+        internal IAsyncObservable<TSource3> Source3 { get; }
+        internal IAsyncObservable<TSource4> Source4 { get; }
+        internal IAsyncObservable<TSource5> Source5 { get; }
+        internal IAsyncObservable<TSource6> Source6 { get; }
+        internal IAsyncObservable<TSource7> Source7 { get; }
+        internal IAsyncObservable<TSource8> Source8 { get; }
+        internal IAsyncObservable<TSource9> Source9 { get; }
+        internal IAsyncObservable<TSource10> Source10 { get; }
+        internal IAsyncObservable<TSource11> Source11 { get; }
+        internal IAsyncObservable<TSource12> Source12 { get; }
+        internal IAsyncObservable<TSource13> Source13 { get; }
+        internal IAsyncObservable<TSource14> Source14 { get; }
+        internal IAsyncObservable<TSource15> Source15 { get; }
+        internal IAsyncObservable<TSource16> Source16 { get; }
+
+        internal AsyncPattern(IAsyncObservable<TSource1> source1, IAsyncObservable<TSource2> source2, IAsyncObservable<TSource3> source3, IAsyncObservable<TSource4> source4, IAsyncObservable<TSource5> source5, IAsyncObservable<TSource6> source6, IAsyncObservable<TSource7> source7, IAsyncObservable<TSource8> source8, IAsyncObservable<TSource9> source9, IAsyncObservable<TSource10> source10, IAsyncObservable<TSource11> source11, IAsyncObservable<TSource12> source12, IAsyncObservable<TSource13> source13, IAsyncObservable<TSource14> source14, IAsyncObservable<TSource15> source15, IAsyncObservable<TSource16> source16)
+        {
+            Source1 = source1;
+            Source2 = source2;
+            Source3 = source3;
+            Source4 = source4;
+            Source5 = source5;
+            Source6 = source6;
+            Source7 = source7;
+            Source8 = source8;
+            Source9 = source9;
+            Source10 = source10;
+            Source11 = source11;
+            Source12 = source12;
+            Source13 = source13;
+            Source14 = source14;
+            Source15 = source15;
+            Source16 = source16;
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult>(this, selector);
+        }
+    }
+
+}

+ 64 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.Generated.tt

@@ -0,0 +1,64 @@
+// 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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+<#
+for (var i = 1; i <= 16; i++)
+{
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "TSource" + j));
+    var args = string.Join(", ", Enumerable.Range(1, i).Select(j => "IAsyncObservable<TSource" + j + "> source" + j));
+#>
+    public class AsyncPattern<<#=genArgs#>> : AsyncPattern
+    {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+        internal IAsyncObservable<TSource<#=j#>> Source<#=j#> { get; }
+<#
+}
+#>
+
+        internal AsyncPattern(<#=args#>)
+        {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            Source<#=j#> = source<#=j#>;
+<#
+}
+#>
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<<#=genArgs#>, TResult> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlan<<#=genArgs#>, TResult>(this, selector);
+        }
+
+        public AsyncPlan<TResult> Then<TResult>(Func<<#=genArgs#>, Task<TResult>> selector)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return new AsyncPlanWithTask<<#=genArgs#>, TResult>(this, selector);
+        }
+    }
+
+<#
+}
+#>
+}

+ 13 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPattern.cs

@@ -0,0 +1,13 @@
+// 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. 
+
+namespace System.Reactive.Joins
+{
+    public abstract class AsyncPattern
+    {
+        internal AsyncPattern()
+        {
+        }
+    }
+}

+ 1706 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.Generated.cs

@@ -0,0 +1,1706 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    internal sealed class AsyncPlan<TSource1, TResult> : AsyncPlanBase<TSource1, TResult>
+    {
+        private readonly Func<TSource1, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1> expression, Func<TSource1, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1) => Task.FromResult(_selector(arg1));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TResult> : AsyncPlanBase<TSource1, TResult>
+    {
+        private readonly Func<TSource1, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1> expression, Func<TSource1, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1) => _selector(arg1);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1>);
+
+            activePlan = new ActiveAsyncPlan<TSource1>(
+                joinObserver1,
+                async (arg1) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TResult> : AsyncPlanBase<TSource1, TSource2, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2> expression, Func<TSource1, TSource2, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2) => Task.FromResult(_selector(arg1, arg2));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TResult> : AsyncPlanBase<TSource1, TSource2, TResult>
+    {
+        private readonly Func<TSource1, TSource2, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2> expression, Func<TSource1, TSource2, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2) => _selector(arg1, arg2);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2>(
+                joinObserver1,
+                joinObserver2,
+                async (arg1, arg2) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3> expression, Func<TSource1, TSource2, TSource3, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3) => Task.FromResult(_selector(arg1, arg2, arg3));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3> expression, Func<TSource1, TSource2, TSource3, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3) => _selector(arg1, arg2, arg3);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                async (arg1, arg2, arg3) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4> expression, Func<TSource1, TSource2, TSource3, TSource4, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4) => Task.FromResult(_selector(arg1, arg2, arg3, arg4));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4> expression, Func<TSource1, TSource2, TSource3, TSource4, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4) => _selector(arg1, arg2, arg3, arg4);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                async (arg1, arg2, arg3, arg4) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5) => _selector(arg1, arg2, arg3, arg4, arg5);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                async (arg1, arg2, arg3, arg4, arg5) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6) => _selector(arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                async (arg1, arg2, arg3, arg4, arg5, arg6) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+            var joinObserver12 = AsyncPlan<TResult>.CreateObserver<TSource12>(externalSubscriptions, _expression.Source12, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                joinObserver12,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver12.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+            joinObserver12.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+            var joinObserver12 = AsyncPlan<TResult>.CreateObserver<TSource12>(externalSubscriptions, _expression.Source12, onError);
+            var joinObserver13 = AsyncPlan<TResult>.CreateObserver<TSource13>(externalSubscriptions, _expression.Source13, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                joinObserver12,
+                joinObserver13,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver12.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver13.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+            joinObserver12.AddActivePlan(activePlan);
+            joinObserver13.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+            var joinObserver12 = AsyncPlan<TResult>.CreateObserver<TSource12>(externalSubscriptions, _expression.Source12, onError);
+            var joinObserver13 = AsyncPlan<TResult>.CreateObserver<TSource13>(externalSubscriptions, _expression.Source13, onError);
+            var joinObserver14 = AsyncPlan<TResult>.CreateObserver<TSource14>(externalSubscriptions, _expression.Source14, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                joinObserver12,
+                joinObserver13,
+                joinObserver14,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver12.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver13.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver14.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+            joinObserver12.AddActivePlan(activePlan);
+            joinObserver13.AddActivePlan(activePlan);
+            joinObserver14.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+            var joinObserver12 = AsyncPlan<TResult>.CreateObserver<TSource12>(externalSubscriptions, _expression.Source12, onError);
+            var joinObserver13 = AsyncPlan<TResult>.CreateObserver<TSource13>(externalSubscriptions, _expression.Source13, onError);
+            var joinObserver14 = AsyncPlan<TResult>.CreateObserver<TSource14>(externalSubscriptions, _expression.Source14, onError);
+            var joinObserver15 = AsyncPlan<TResult>.CreateObserver<TSource15>(externalSubscriptions, _expression.Source15, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                joinObserver12,
+                joinObserver13,
+                joinObserver14,
+                joinObserver15,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver12.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver13.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver14.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver15.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+            joinObserver12.AddActivePlan(activePlan);
+            joinObserver13.AddActivePlan(activePlan);
+            joinObserver14.AddActivePlan(activePlan);
+            joinObserver15.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+    internal sealed class AsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15, TSource16 arg16) => Task.FromResult(_selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16));
+    }
+
+    internal sealed class AsyncPlanWithTask<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> : AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult>
+    {
+        private readonly Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> expression, Func<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15, TSource16 arg16) => _selector(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16);
+    }
+
+    internal abstract class AsyncPlanBase<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(TSource1 arg1, TSource2 arg2, TSource3 arg3, TSource4 arg4, TSource5 arg5, TSource6 arg6, TSource7 arg7, TSource8 arg8, TSource9 arg9, TSource10 arg10, TSource11 arg11, TSource12 arg12, TSource13 arg13, TSource14 arg14, TSource15 arg15, TSource16 arg16); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+            var joinObserver1 = AsyncPlan<TResult>.CreateObserver<TSource1>(externalSubscriptions, _expression.Source1, onError);
+            var joinObserver2 = AsyncPlan<TResult>.CreateObserver<TSource2>(externalSubscriptions, _expression.Source2, onError);
+            var joinObserver3 = AsyncPlan<TResult>.CreateObserver<TSource3>(externalSubscriptions, _expression.Source3, onError);
+            var joinObserver4 = AsyncPlan<TResult>.CreateObserver<TSource4>(externalSubscriptions, _expression.Source4, onError);
+            var joinObserver5 = AsyncPlan<TResult>.CreateObserver<TSource5>(externalSubscriptions, _expression.Source5, onError);
+            var joinObserver6 = AsyncPlan<TResult>.CreateObserver<TSource6>(externalSubscriptions, _expression.Source6, onError);
+            var joinObserver7 = AsyncPlan<TResult>.CreateObserver<TSource7>(externalSubscriptions, _expression.Source7, onError);
+            var joinObserver8 = AsyncPlan<TResult>.CreateObserver<TSource8>(externalSubscriptions, _expression.Source8, onError);
+            var joinObserver9 = AsyncPlan<TResult>.CreateObserver<TSource9>(externalSubscriptions, _expression.Source9, onError);
+            var joinObserver10 = AsyncPlan<TResult>.CreateObserver<TSource10>(externalSubscriptions, _expression.Source10, onError);
+            var joinObserver11 = AsyncPlan<TResult>.CreateObserver<TSource11>(externalSubscriptions, _expression.Source11, onError);
+            var joinObserver12 = AsyncPlan<TResult>.CreateObserver<TSource12>(externalSubscriptions, _expression.Source12, onError);
+            var joinObserver13 = AsyncPlan<TResult>.CreateObserver<TSource13>(externalSubscriptions, _expression.Source13, onError);
+            var joinObserver14 = AsyncPlan<TResult>.CreateObserver<TSource14>(externalSubscriptions, _expression.Source14, onError);
+            var joinObserver15 = AsyncPlan<TResult>.CreateObserver<TSource15>(externalSubscriptions, _expression.Source15, onError);
+            var joinObserver16 = AsyncPlan<TResult>.CreateObserver<TSource16>(externalSubscriptions, _expression.Source16, onError);
+
+            var activePlan = default(ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16>);
+
+            activePlan = new ActiveAsyncPlan<TSource1, TSource2, TSource3, TSource4, TSource5, TSource6, TSource7, TSource8, TSource9, TSource10, TSource11, TSource12, TSource13, TSource14, TSource15, TSource16>(
+                joinObserver1,
+                joinObserver2,
+                joinObserver3,
+                joinObserver4,
+                joinObserver5,
+                joinObserver6,
+                joinObserver7,
+                joinObserver8,
+                joinObserver9,
+                joinObserver10,
+                joinObserver11,
+                joinObserver12,
+                joinObserver13,
+                joinObserver14,
+                joinObserver15,
+                joinObserver16,
+                async (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    await joinObserver1.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver2.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver3.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver4.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver5.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver6.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver7.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver8.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver9.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver10.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver11.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver12.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver13.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver14.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver15.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await joinObserver16.RemoveActivePlan(activePlan).ConfigureAwait(false);
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+            joinObserver1.AddActivePlan(activePlan);
+            joinObserver2.AddActivePlan(activePlan);
+            joinObserver3.AddActivePlan(activePlan);
+            joinObserver4.AddActivePlan(activePlan);
+            joinObserver5.AddActivePlan(activePlan);
+            joinObserver6.AddActivePlan(activePlan);
+            joinObserver7.AddActivePlan(activePlan);
+            joinObserver8.AddActivePlan(activePlan);
+            joinObserver9.AddActivePlan(activePlan);
+            joinObserver10.AddActivePlan(activePlan);
+            joinObserver11.AddActivePlan(activePlan);
+            joinObserver12.AddActivePlan(activePlan);
+            joinObserver13.AddActivePlan(activePlan);
+            joinObserver14.AddActivePlan(activePlan);
+            joinObserver15.AddActivePlan(activePlan);
+            joinObserver16.AddActivePlan(activePlan);
+
+            return activePlan;
+        }
+    }
+
+}

+ 131 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.Generated.tt

@@ -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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+<#
+for (var i = 1; i <= 16; i++)
+{
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "TSource" + j));
+    var args = string.Join(", ", Enumerable.Range(1, i).Select(j => "IObservable<TSource" + j + "> source" + j));
+    var pars = string.Join(", ", Enumerable.Range(1, i).Select(j => "arg" + j));
+    var evalPars = string.Join(", ", Enumerable.Range(1, i).Select(j => "TSource" + j + " arg" + j));
+#>
+    internal sealed class AsyncPlan<<#=genArgs#>, TResult> : AsyncPlanBase<<#=genArgs#>, TResult>
+    {
+        private readonly Func<<#=genArgs#>, TResult> _selector;
+
+        internal AsyncPlan(AsyncPattern<<#=genArgs#>> expression, Func<<#=genArgs#>, TResult> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(<#=evalPars#>) => Task.FromResult(_selector(<#=pars#>));
+    }
+
+    internal sealed class AsyncPlanWithTask<<#=genArgs#>, TResult> : AsyncPlanBase<<#=genArgs#>, TResult>
+    {
+        private readonly Func<<#=genArgs#>, Task<TResult>> _selector;
+
+        internal AsyncPlanWithTask(AsyncPattern<<#=genArgs#>> expression, Func<<#=genArgs#>, Task<TResult>> selector)
+            : base(expression)
+        {
+            _selector = selector;
+        }
+
+        protected override Task<TResult> EvalAsync(<#=evalPars#>) => _selector(<#=pars#>);
+    }
+
+    internal abstract class AsyncPlanBase<<#=genArgs#>, TResult> : AsyncPlan<TResult>
+    {
+        private readonly AsyncPattern<<#=genArgs#>> _expression;
+
+        internal AsyncPlanBase(AsyncPattern<<#=genArgs#>> expression)
+        {
+            _expression = expression;
+        }
+
+        protected abstract Task<TResult> EvalAsync(<#=evalPars#>); // REVIEW: Consider the use of ValueTask<TResult>.
+
+        internal override ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate)
+        {
+            var onError = new Func<Exception, Task>(observer.OnErrorAsync);
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            var joinObserver<#=j#> = AsyncPlan<TResult>.CreateObserver<TSource<#=j#>>(externalSubscriptions, _expression.Source<#=j#>, onError);
+<#
+}
+#>
+
+            var activePlan = default(ActiveAsyncPlan<<#=genArgs#>>);
+
+            activePlan = new ActiveAsyncPlan<<#=genArgs#>>(
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                joinObserver<#=j#>,
+<#
+}
+#>
+                async (<#=pars#>) =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await EvalAsync(<#=pars#>).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                },
+                async () =>
+                {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                    await joinObserver<#=j#>.RemoveActivePlan(activePlan).ConfigureAwait(false);
+<#
+}
+#>
+                    await deactivate(activePlan).ConfigureAwait(false);
+                }
+            );
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            joinObserver<#=j#>.AddActivePlan(activePlan);
+<#
+}
+#>
+
+            return activePlan;
+        }
+    }
+
+<#
+}
+#>
+}

+ 35 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/AsyncPlan.cs

@@ -0,0 +1,35 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    public abstract class AsyncPlan<TResult>
+    {
+        internal AsyncPlan()
+        {
+        }
+
+        internal abstract ActiveAsyncPlan Activate(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObserver<TResult> observer, Func<ActiveAsyncPlan, Task> deactivate);
+
+        internal static AsyncJoinObserver<TSource> CreateObserver<TSource>(Dictionary<object, IAsyncJoinObserver> externalSubscriptions, IAsyncObservable<TSource> observable, Func<Exception, Task> onError)
+        {
+            var res = default(AsyncJoinObserver<TSource>);
+
+            if (externalSubscriptions.TryGetValue(observable, out var joinObserver))
+            {
+                res = (AsyncJoinObserver<TSource>)joinObserver;
+            }
+            else
+            {
+                res = new AsyncJoinObserver<TSource>(observable, onError);
+                externalSubscriptions.Add(observable, res);
+            }
+
+            return res;
+        }
+    }
+}

+ 16 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Joins/IAsyncJoinObserver.cs

@@ -0,0 +1,16 @@
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Joins
+{
+    internal interface IAsyncJoinObserver : IAsyncDisposable
+    {
+        Task SubscribeAsync(AsyncLock gate);
+
+        void Dequeue();
+    }
+}

+ 44 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/AsyncObservable.cs

@@ -0,0 +1,44 @@
+// 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.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    public static partial class AsyncObservable
+    {
+        public static IAsyncObservable<T> Create<T>(Func<IAsyncObserver<T>, Task<IAsyncDisposable>> subscribeAsync)
+        {
+            if (subscribeAsync == null)
+                throw new ArgumentNullException(nameof(subscribeAsync));
+
+            return new AsyncObservable<T>(subscribeAsync);
+        }
+
+        public static Task<IAsyncDisposable> SubscribeSafeAsync<T>(this IAsyncObservable<T> source, IAsyncObserver<T> observer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return CoreAsync();
+
+            async Task<IAsyncDisposable> CoreAsync()
+            {
+                try
+                {
+                    return await source.SubscribeAsync(observer).ConfigureAwait(false);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+
+                    return AsyncDisposable.Nop;
+                }
+            }
+        }
+    }
+}

+ 47 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/AsyncObserver.cs

@@ -0,0 +1,47 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    public static partial class AsyncObserver
+    {
+        public static IAsyncObserver<T> Create<T>(Func<T, Task> onNextAsync)
+        {
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+
+            return new AsyncObserver<T>(
+                onNextAsync,
+                ex => Task.FromException(ex),
+                () => Task.CompletedTask
+            );
+        }
+
+        public static IAsyncObserver<T> Create<T>(Func<T, Task> onNextAsync, Func<Exception, Task> onErrorAsync, Func<Task> onCompletedAsync)
+        {
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onErrorAsync == null)
+                throw new ArgumentNullException(nameof(onErrorAsync));
+            if (onCompletedAsync == null)
+                throw new ArgumentNullException(nameof(onCompletedAsync));
+
+            return new AsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync);
+        }
+
+        internal static IAsyncObserver<T> CreateUnsafe<T>(Func<T, Task> onNextAsync, Func<Exception, Task> onErrorAsync, Func<Task> onCompletedAsync)
+        {
+            if (onNextAsync == null)
+                throw new ArgumentNullException(nameof(onNextAsync));
+            if (onErrorAsync == null)
+                throw new ArgumentNullException(nameof(onErrorAsync));
+            if (onCompletedAsync == null)
+                throw new ArgumentNullException(nameof(onCompletedAsync));
+
+            return new UnsafeAsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync);
+        }
+    }
+}

+ 37 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/GroupedAsyncObservable.cs

@@ -0,0 +1,37 @@
+// 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.Reactive.Disposables;
+using System.Reactive.Subjects;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    internal sealed class GroupedAsyncObservable<TKey, TElement> : AsyncObservableBase<TElement>, IGroupedAsyncObservable<TKey, TElement>
+    {
+        private readonly IAsyncSubject<TElement> _subject;
+        private readonly RefCountAsyncDisposable _disposable;
+
+        public GroupedAsyncObservable(TKey key, IAsyncSubject<TElement> subject, RefCountAsyncDisposable disposable)
+        {
+            Key = key;
+            _subject = subject;
+            _disposable = disposable;
+        }
+
+        public TKey Key { get; }
+
+        protected override async Task<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<TElement> observer)
+        {
+            if (_disposable != null)
+            {
+                var d = await _disposable.GetDisposableAsync().ConfigureAwait(false);
+                var s = await _subject.SubscribeAsync(observer).ConfigureAwait(false);
+                return StableCompositeAsyncDisposable.Create(d, s);
+            }
+
+            return await _subject.SubscribeAsync(observer).ConfigureAwait(false);
+        }
+    }
+}

+ 282 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Aggregate.cs

@@ -0,0 +1,282 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Aggregate<TSource>(this IAsyncObservable<TSource> source, Func<TSource, TSource, TSource> func)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, func)));
+        }
+
+        public static IAsyncObservable<TSource> Aggregate<TSource>(this IAsyncObservable<TSource> source, Func<TSource, TSource, Task<TSource>> func)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, func)));
+        }
+
+        public static IAsyncObservable<TResult> Aggregate<TSource, TResult>(this IAsyncObservable<TSource> source, TResult seed, Func<TResult, TSource, TResult> func)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TResult>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, seed, func)));
+        }
+
+        public static IAsyncObservable<TResult> Aggregate<TSource, TResult>(this IAsyncObservable<TSource> source, TResult seed, Func<TResult, TSource, Task<TResult>> func)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TResult>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, seed, func)));
+        }
+
+        public static IAsyncObservable<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TResult>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, seed, func, resultSelector)));
+        }
+
+        public static IAsyncObservable<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, Task<TAccumulate>> func, Func<TAccumulate, Task<TResult>> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Create<TResult>(observer => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, seed, func, resultSelector)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Aggregate<TSource>(IAsyncObserver<TSource> observer, Func<TSource, TSource, TSource> func)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            var hasValue = false;
+            var value = default(TSource);
+
+            return Create<TSource>(
+                async x =>
+                {
+                    if (hasValue)
+                    {
+                        try
+                        {
+                            value = func(value, x);
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        value = x;
+                        hasValue = true;
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (!hasValue)
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(value).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Aggregate<TSource>(IAsyncObserver<TSource> observer, Func<TSource, TSource, Task<TSource>> func)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            var hasValue = false;
+            var value = default(TSource);
+
+            return Create<TSource>(
+                async x =>
+                {
+                    if (hasValue)
+                    {
+                        try
+                        {
+                            value = await func(value, x).ConfigureAwait(false);
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        value = x;
+                        hasValue = true;
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (!hasValue)
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(value).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Aggregate<TSource, TResult>(IAsyncObserver<TResult> observer, TResult seed, Func<TResult, TSource, TResult> func)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Aggregate(observer, seed, func, a => a);
+        }
+
+        public static IAsyncObserver<TSource> Aggregate<TSource, TResult>(IAsyncObserver<TResult> observer, TResult seed, Func<TResult, TSource, Task<TResult>> func)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            return Aggregate<TSource, TResult, TResult>(observer, seed, (a, x) => func(a, x), a => Task.FromResult(a));
+        }
+
+        public static IAsyncObserver<TSource> Aggregate<TSource, TAccumulate, TResult>(IAsyncObserver<TResult> observer, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            var value = seed;
+
+            return Create<TSource>(
+                async x =>
+                {
+                    try
+                    {
+                        value = func(value, x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = resultSelector(value);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Aggregate<TSource, TAccumulate, TResult>(IAsyncObserver<TResult> observer, TAccumulate seed, Func<TAccumulate, TSource, Task<TAccumulate>> func, Func<TAccumulate, Task<TResult>> resultSelector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (func == null)
+                throw new ArgumentNullException(nameof(func));
+
+            var value = seed;
+
+            return Create<TSource>(
+                async x =>
+                {
+                    try
+                    {
+                        value = await func(value, x).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    var res = default(TResult);
+
+                    try
+                    {
+                        res = await resultSelector(value).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(res).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 108 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/All.cs

@@ -0,0 +1,108 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<bool> All<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.All(observer, predicate)));
+        }
+
+        public static IAsyncObservable<bool> All<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.All(observer, predicate)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> All<TSource>(IAsyncObserver<bool> observer, Func<TSource, bool> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = predicate(x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (!b)
+                    {
+                        await observer.OnNextAsync(false).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(true).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> All<TSource>(IAsyncObserver<bool> observer, Func<TSource, Task<bool>> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = await predicate(x).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (!b)
+                    {
+                        await observer.OnNextAsync(false).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(true).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 288 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Amb.cs

@@ -0,0 +1,288 @@
+// 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.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Amb<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return Create<TSource>(async observer =>
+            {
+                var firstSubscription = new SingleAssignmentAsyncDisposable();
+                var secondSubscription = new SingleAssignmentAsyncDisposable();
+
+                var (firstObserver, secondObserver) = AsyncObserver.Amb(observer, firstSubscription, secondSubscription);
+
+                var firstTask = first.SubscribeSafeAsync(firstObserver).ContinueWith(d => firstSubscription.AssignAsync(d.Result)).Unwrap();
+                var secondTask = second.SubscribeSafeAsync(secondObserver).ContinueWith(d => secondSubscription.AssignAsync(d.Result)).Unwrap();
+
+                await Task.WhenAll(firstTask, secondTask).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(firstSubscription, secondSubscription);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Amb<TSource>(this IEnumerable<IAsyncObservable<TSource>> sources) => Amb(sources.ToArray());
+
+        public static IAsyncObservable<TSource> Amb<TSource>(params IAsyncObservable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return Create<TSource>(async observer =>
+            {
+                var count = sources.Length;
+
+                var subscriptions = new SingleAssignmentAsyncDisposable[count];
+
+                for (var i = 0; i < count; i++)
+                {
+                    subscriptions[i] = new SingleAssignmentAsyncDisposable();
+                }
+
+                var observers = AsyncObserver.Amb(observer, subscriptions);
+
+                var tasks = new Task[count];
+
+                for (var i = 0; i < count; i++)
+                {
+                    tasks[i] = sources[i].SubscribeSafeAsync(observers[i]).ContinueWith(d => subscriptions[i].AssignAsync(d.Result)).Unwrap();
+                }
+
+                await Task.WhenAll(tasks).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscriptions);
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static (IAsyncObserver<TSource>, IAsyncObserver<TSource>) Amb<TSource>(IAsyncObserver<TSource> observer, IAsyncDisposable first, IAsyncDisposable second)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            var gate = new AsyncLock();
+
+            var state = AmbState.None;
+
+            return
+                (
+                    Create<TSource>(
+                        async x =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.First;
+                                    await second.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.First)
+                                {
+                                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                                }
+                            }
+                        },
+                        async ex =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.First;
+                                    await second.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.First)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                }
+                            }
+                        },
+                        async () =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.First;
+                                    await second.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.First)
+                                {
+                                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                                }
+                            }
+                        }
+                    ),
+                    Create<TSource>(
+                        async x =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.Second;
+                                    await first.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.Second)
+                                {
+                                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                                }
+                            }
+                        },
+                        async ex =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.Second;
+                                    await first.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.Second)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                }
+                            }
+                        },
+                        async () =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                if (state == AmbState.None)
+                                {
+                                    state = AmbState.Second;
+                                    await first.DisposeAsync().ConfigureAwait(false);
+                                }
+
+                                if (state == AmbState.Second)
+                                {
+                                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                                }
+                            }
+                        }
+                    )
+                );
+        }
+
+        public static IAsyncObserver<TSource>[] Amb<TSource>(IAsyncObserver<TSource> observer, IAsyncDisposable[] subscriptions)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (subscriptions == null)
+                throw new ArgumentNullException(nameof(subscriptions));
+
+            var gate = new AsyncLock();
+
+            var winner = default(int?);
+
+            var count = subscriptions.Length;
+
+            async Task ElectWinnerAsync(int index)
+            {
+                winner = index;
+
+                var dispose = new List<Task>(count - 1);
+
+                for (var i = 0; i < count; i++)
+                {
+                    if (i != index)
+                    {
+                        dispose.Add(subscriptions[i].DisposeAsync());
+                    }
+                }
+
+                await Task.WhenAll(dispose).ConfigureAwait(false);
+            }
+
+            IAsyncObserver<TSource> CreateObserver(int index) =>
+                Create<TSource>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (winner == null)
+                            {
+                                await ElectWinnerAsync(index).ConfigureAwait(false);
+                            }
+
+                            if (winner == index)
+                            {
+                                await observer.OnNextAsync(x).ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (winner == null)
+                            {
+                                await ElectWinnerAsync(index).ConfigureAwait(false);
+                            }
+
+                            if (winner == index)
+                            {
+                                await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (winner == null)
+                            {
+                                await ElectWinnerAsync(index).ConfigureAwait(false);
+                            }
+
+                            if (winner == index)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                );
+
+            var res = new IAsyncObserver<TSource>[count];
+
+            for (var i = 0; i < count; i++)
+            {
+                res[i] = CreateObserver(i);
+            }
+
+            return res;
+        }
+
+        private enum AmbState
+        {
+            None,
+            First,
+            Second,
+        }
+    }
+}

+ 23 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/And.cs

@@ -0,0 +1,23 @@
+// 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.Reactive.Joins;
+
+namespace System.Reactive.Linq
+{
+    // REVIEW: Consider moving join patterns to a separate assembly.
+
+    partial class AsyncObservable
+    {
+        public static AsyncPattern<TLeft, TRight> And<TLeft, TRight>(this IAsyncObservable<TLeft> left, IAsyncObservable<TRight> right)
+        {
+            if (left == null)
+                throw new ArgumentNullException(nameof(left));
+            if (right == null)
+                throw new ArgumentNullException(nameof(right));
+
+            return new AsyncPattern<TLeft, TRight>(left, right);
+        }
+    }
+}

+ 136 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Any.cs

@@ -0,0 +1,136 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<bool> Any<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.Any<TSource>(observer)));
+        }
+
+        public static IAsyncObservable<bool> Any<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.Any(observer, predicate)));
+        }
+
+        public static IAsyncObservable<bool> Any<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.Any(observer, predicate)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Any<TSource>(IAsyncObserver<bool> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    await observer.OnNextAsync(true).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(false).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Any<TSource>(IAsyncObserver<bool> observer, Func<TSource, bool> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = predicate(x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        await observer.OnNextAsync(true).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(false).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Any<TSource>(IAsyncObserver<bool> observer, Func<TSource, Task<bool>> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = await predicate(x).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        await observer.OnNextAsync(true).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(false).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 319 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Append.cs

@@ -0,0 +1,319 @@
+// 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.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, TSource value)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Append(observer, value)));
+        }
+
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, TSource value, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<TSource>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (sink, disposable) = AsyncObserver.Append(observer, value, scheduler);
+
+                await d.AddAsync(disposable).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                await d.AddAsync(subscription).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, params TSource[] values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Append(observer, values)));
+        }
+
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler scheduler, params TSource[] values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (sink, disposable) = AsyncObserver.Append(observer, scheduler, values);
+
+                await d.AddAsync(disposable).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                await d.AddAsync(subscription).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, IEnumerable<TSource> values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Append(observer, values)));
+        }
+
+        public static IAsyncObservable<TSource> Append<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler scheduler, IEnumerable<TSource> values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (sink, disposable) = AsyncObserver.Append(observer, scheduler, values);
+
+                await d.AddAsync(disposable).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                await d.AddAsync(subscription).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Append<TSource>(IAsyncObserver<TSource> observer, TSource value)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(
+                observer.OnNextAsync,
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(value).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Append<TSource>(IAsyncObserver<TSource> observer, TSource value, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            var d = new SingleAssignmentAsyncDisposable();
+
+            return
+                (
+                    Create<TSource>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        async () =>
+                        {
+                            var task = await scheduler.ScheduleAsync(async ct =>
+                            {
+                                if (!ct.IsCancellationRequested)
+                                {
+                                    await observer.OnNextAsync(value).RendezVous(scheduler, ct);
+                                    await observer.OnCompletedAsync().RendezVous(scheduler, ct);
+                                }
+                            }).ConfigureAwait(false);
+
+                            await d.AssignAsync(task).ConfigureAwait(false);
+                        }
+                    ),
+                    d
+                );
+        }
+
+        public static IAsyncObserver<TSource> Append<TSource>(IAsyncObserver<TSource> observer, params TSource[] values)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(
+                observer.OnNextAsync,
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    foreach (var value in values)
+                    {
+                        await observer.OnNextAsync(value).ConfigureAwait(false);
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Append<TSource>(IAsyncObserver<TSource> observer, IAsyncScheduler scheduler, params TSource[] values)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            var d = new SingleAssignmentAsyncDisposable();
+
+            return
+                (
+                    Create<TSource>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        async () =>
+                        {
+                            var task = await scheduler.ScheduleAsync(async ct =>
+                            {
+                                for (var i = 0; i < values.Length && !ct.IsCancellationRequested; i++)
+                                {
+                                    await observer.OnNextAsync(values[i]).RendezVous(scheduler, ct);
+                                }
+
+                                await observer.OnCompletedAsync().RendezVous(scheduler, ct);
+                            }).ConfigureAwait(false);
+
+                            await d.AssignAsync(task).ConfigureAwait(false);
+                        }
+                    ),
+                    d
+                );
+        }
+
+        public static IAsyncObserver<TSource> Append<TSource>(IAsyncObserver<TSource> observer, IEnumerable<TSource> values)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+
+            return Create<TSource>(
+                observer.OnNextAsync,
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    foreach (var value in values)
+                    {
+                        await observer.OnNextAsync(value).ConfigureAwait(false);
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Append<TSource>(IAsyncObserver<TSource> observer, IAsyncScheduler scheduler, IEnumerable<TSource> values)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (values == null)
+                throw new ArgumentNullException(nameof(values));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            var d = new SingleAssignmentAsyncDisposable();
+
+            return
+                (
+                    Create<TSource>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        async () =>
+                        {
+                            var task = await scheduler.ScheduleAsync(async ct =>
+                            {
+                                var e = default(IEnumerator<TSource>);
+
+                                try
+                                {
+                                    e = values.GetEnumerator();
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).RendezVous(scheduler, ct);
+                                    return;
+                                }
+
+                                using (e)
+                                {
+                                    while (!ct.IsCancellationRequested)
+                                    {
+                                        var b = default(bool);
+                                        var value = default(TSource);
+
+                                        try
+                                        {
+                                            b = e.MoveNext();
+
+                                            if (b)
+                                            {
+                                                value = e.Current;
+                                            }
+                                        }
+                                        catch (Exception ex)
+                                        {
+                                            await observer.OnErrorAsync(ex).RendezVous(scheduler, ct);
+                                            return;
+                                        }
+
+                                        if (b)
+                                        {
+                                            await observer.OnNextAsync(value).RendezVous(scheduler, ct);
+                                        }
+                                        else
+                                        {
+                                            break;
+                                        }
+                                    }
+                                }
+
+                                await observer.OnCompletedAsync().RendezVous(scheduler, ct);
+                            }).ConfigureAwait(false);
+
+                            await d.AssignAsync(task).ConfigureAwait(false);
+                        }
+                    ),
+                    d
+                );
+        }
+    }
+}

+ 17 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/AsAsyncObservable.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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> AsAsyncObservable<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(observer));
+        }
+    }
+}

+ 496 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.Generated.cs

@@ -0,0 +1,496 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<Double> Average(this IAsyncObservable<Int32> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt32(observer)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int32> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt32(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Int32>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt32(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average(this IAsyncObservable<Int32?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt32(observer)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int32?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt32(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Int32?>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt32(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double> Average(this IAsyncObservable<Int64> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt64(observer)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int64> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt64(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Int64>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageInt64(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average(this IAsyncObservable<Int64?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt64(observer)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int64?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt64(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Int64?>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableInt64(observer, selector)));
+        }
+
+        public static IAsyncObservable<Single> Average(this IAsyncObservable<Single> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Single>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageSingle(observer)));
+        }
+
+        public static IAsyncObservable<Single> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Single> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Single>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageSingle(observer, selector)));
+        }
+
+        public static IAsyncObservable<Single> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Single>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Single>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageSingle(observer, selector)));
+        }
+
+        public static IAsyncObservable<Single?> Average(this IAsyncObservable<Single?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Single?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableSingle(observer)));
+        }
+
+        public static IAsyncObservable<Single?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Single?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Single?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableSingle(observer, selector)));
+        }
+
+        public static IAsyncObservable<Single?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Single?>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Single?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableSingle(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double> Average(this IAsyncObservable<Double> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDouble(observer)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Double> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDouble(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Double>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDouble(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average(this IAsyncObservable<Double?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDouble(observer)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Double?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDouble(observer, selector)));
+        }
+
+        public static IAsyncObservable<Double?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Double?>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Double?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDouble(observer, selector)));
+        }
+
+        public static IAsyncObservable<Decimal> Average(this IAsyncObservable<Decimal> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Decimal>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDecimal(observer)));
+        }
+
+        public static IAsyncObservable<Decimal> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Decimal> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Decimal>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDecimal(observer, selector)));
+        }
+
+        public static IAsyncObservable<Decimal> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Decimal>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Decimal>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageDecimal(observer, selector)));
+        }
+
+        public static IAsyncObservable<Decimal?> Average(this IAsyncObservable<Decimal?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<Decimal?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDecimal(observer)));
+        }
+
+        public static IAsyncObservable<Decimal?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Decimal?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Decimal?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDecimal(observer, selector)));
+        }
+
+        public static IAsyncObservable<Decimal?> Average<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<Decimal?>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<Decimal?>(observer => source.SubscribeSafeAsync(AsyncObserver.AverageNullableDecimal(observer, selector)));
+        }
+
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> AverageInt32<TSource>(IAsyncObserver<Double> observer, Func<TSource, Int32> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageInt32(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageInt32<TSource>(IAsyncObserver<Double> observer, Func<TSource, Task<Int32>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageInt32(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableInt32<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Int32?> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableInt32(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableInt32<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Task<Int32?>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableInt32(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageInt64<TSource>(IAsyncObserver<Double> observer, Func<TSource, Int64> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageInt64(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageInt64<TSource>(IAsyncObserver<Double> observer, Func<TSource, Task<Int64>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageInt64(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableInt64<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Int64?> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableInt64(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableInt64<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Task<Int64?>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableInt64(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageSingle<TSource>(IAsyncObserver<Single> observer, Func<TSource, Single> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageSingle(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageSingle<TSource>(IAsyncObserver<Single> observer, Func<TSource, Task<Single>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageSingle(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableSingle<TSource>(IAsyncObserver<Single?> observer, Func<TSource, Single?> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableSingle(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableSingle<TSource>(IAsyncObserver<Single?> observer, Func<TSource, Task<Single?>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableSingle(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageDouble<TSource>(IAsyncObserver<Double> observer, Func<TSource, Double> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageDouble(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageDouble<TSource>(IAsyncObserver<Double> observer, Func<TSource, Task<Double>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageDouble(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableDouble<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Double?> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableDouble(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableDouble<TSource>(IAsyncObserver<Double?> observer, Func<TSource, Task<Double?>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableDouble(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageDecimal<TSource>(IAsyncObserver<Decimal> observer, Func<TSource, Decimal> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageDecimal(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageDecimal<TSource>(IAsyncObserver<Decimal> observer, Func<TSource, Task<Decimal>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageDecimal(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableDecimal<TSource>(IAsyncObserver<Decimal?> observer, Func<TSource, Decimal?> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableDecimal(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> AverageNullableDecimal<TSource>(IAsyncObserver<Decimal?> observer, Func<TSource, Task<Decimal?>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(AverageNullableDecimal(observer), selector);
+        }
+
+    }
+}

+ 115 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.Generated.tt

@@ -0,0 +1,115 @@
+// 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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+<#
+var types = new[]
+{
+    new { source = typeof(int),     target = typeof(double)  },
+    new { source = typeof(long),    target = typeof(double)  },
+    new { source = typeof(float),   target = typeof(float)   },
+    new { source = typeof(double),  target = typeof(double)  },
+    new { source = typeof(decimal), target = typeof(decimal) },
+};
+var name = "Average";
+#>
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+<#
+foreach (var t in types)
+{
+    var sourceType = t.source;
+    var targetType = t.target;
+
+    foreach (var n in new[] { false, true })
+    {
+        var sourceTypeName = n ? sourceType.Name + "?" : sourceType.Name;
+        var targetTypeName = n ? targetType.Name + "?" : targetType.Name;
+        var methodName = n ? "Nullable" + sourceType.Name : sourceType.Name;
+
+#>
+        public static IAsyncObservable<<#=targetTypeName#>> <#=name#>(this IAsyncObservable<<#=sourceTypeName#>> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<<#=targetTypeName#>>(observer => source.SubscribeSafeAsync(AsyncObserver.<#=name#><#=methodName#>(observer)));
+        }
+
+        public static IAsyncObservable<<#=targetTypeName#>> <#=name#><TSource>(this IAsyncObservable<TSource> source, Func<TSource, <#=sourceTypeName#>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<<#=targetTypeName#>>(observer => source.SubscribeSafeAsync(AsyncObserver.<#=name#><#=methodName#>(observer, selector)));
+        }
+
+        public static IAsyncObservable<<#=targetTypeName#>> <#=name#><TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<<#=sourceTypeName#>>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<<#=targetTypeName#>>(observer => source.SubscribeSafeAsync(AsyncObserver.<#=name#><#=methodName#>(observer, selector)));
+        }
+
+<#
+    }
+}
+#>
+    }
+
+    partial class AsyncObserver
+    {
+<#
+foreach (var t in types)
+{
+    var sourceType = t.source;
+    var targetType = t.target;
+
+    foreach (var n in new[] { false, true })
+    {
+        var sourceTypeName = n ? sourceType.Name + "?" : sourceType.Name;
+        var targetTypeName = n ? targetType.Name + "?" : targetType.Name;
+        var methodName = n ? "Nullable" + sourceType.Name : sourceType.Name;
+
+#>
+        public static IAsyncObserver<TSource> <#=name#><#=methodName#><TSource>(IAsyncObserver<<#=targetTypeName#>> observer, Func<TSource, <#=sourceTypeName#>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(<#=name#><#=methodName#>(observer), selector);
+        }
+
+        public static IAsyncObserver<TSource> <#=name#><#=methodName#><TSource>(IAsyncObserver<<#=targetTypeName#>> observer, Func<TSource, Task<<#=sourceTypeName#>>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Select(<#=name#><#=methodName#>(observer), selector);
+        }
+
+<#
+    }
+}
+#>
+    }
+}

+ 579 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Average.cs

@@ -0,0 +1,579 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<int> AverageInt32(IAsyncObserver<double> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0L;
+            var count = 0L;
+
+            return Create<int>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            sum += x;
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (double)sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<long> AverageInt64(IAsyncObserver<double> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0L;
+            var count = 0L;
+
+            return Create<long>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            sum += x;
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (double)sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<float> AverageSingle(IAsyncObserver<float> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0.0;
+            var count = 0L;
+
+            return Create<float>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            sum += x;
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(float);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (float)(sum / count);
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<double> AverageDouble(IAsyncObserver<double> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0.0;
+            var count = 0L;
+
+            return Create<double>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            sum += x;
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<decimal> AverageDecimal(IAsyncObserver<decimal> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0m;
+            var count = 0L;
+
+            return Create<decimal>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            sum += x;
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(decimal);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<int?> AverageNullableInt32(IAsyncObserver<double?> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0L;
+            var count = 0L;
+
+            return Create<int?>(
+                async x =>
+                {
+                    try
+                    {
+                        if (x.HasValue)
+                        {
+                            checked
+                            {
+                                sum += x.GetValueOrDefault();
+                                count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (double)sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(null).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<long?> AverageNullableInt64(IAsyncObserver<double?> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0L;
+            var count = 0L;
+
+            return Create<long?>(
+                async x =>
+                {
+                    try
+                    {
+                        if (x.HasValue)
+                        {
+                            checked
+                            {
+                                sum += x.GetValueOrDefault();
+                                count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (double)sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(null).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<float?> AverageNullableSingle(IAsyncObserver<float?> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0.0;
+            var count = 0L;
+
+            return Create<float?>(
+                async x =>
+                {
+                    try
+                    {
+                        if (x.HasValue)
+                        {
+                            checked
+                            {
+                                sum += x.GetValueOrDefault();
+                                count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(float);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = (float)(sum / count);
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(null).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<double?> AverageNullableDouble(IAsyncObserver<double?> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0.0;
+            var count = 0L;
+
+            return Create<double?>(
+                async x =>
+                {
+                    try
+                    {
+                        if (x.HasValue)
+                        {
+                            checked
+                            {
+                                sum += x.GetValueOrDefault();
+                                count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(double);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(null).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+
+        public static IAsyncObserver<decimal?> AverageNullableDecimal(IAsyncObserver<decimal?> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var sum = 0m;
+            var count = 0L;
+
+            return Create<decimal?>(
+                async x =>
+                {
+                    try
+                    {
+                        if (x.HasValue)
+                        {
+                            checked
+                            {
+                                sum += x.GetValueOrDefault();
+                                count++;
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (count > 0)
+                    {
+                        var res = default(decimal);
+
+                        try
+                        {
+                            checked
+                            {
+                                res = sum / count;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+
+                        await observer.OnNextAsync(res).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnNextAsync(null).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+            );
+        }
+    }
+}

+ 725 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Buffer.cs

@@ -0,0 +1,725 @@
+// 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.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+
+            return Create<IList<TSource>>(observer => source.SubscribeSafeAsync(AsyncObserver.Buffer(observer, count)));
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, int count, int skip)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+            if (skip <= 0)
+                throw new ArgumentNullException(nameof(skip));
+
+            return Create<IList<TSource>>(observer => source.SubscribeSafeAsync(AsyncObserver.Buffer(observer, count, skip)));
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, scheduler).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (timeShift < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeShift));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, timeShift).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (timeShift < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeShift));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, timeShift, scheduler).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, count).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan, int count, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, count, scheduler).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, timer);
+            });
+        }
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource, TBufferBoundary>(this IAsyncObservable<TSource> source, IAsyncObservable<TBufferBoundary> bufferBoundaries)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (bufferBoundaries == null)
+                throw new ArgumentNullException(nameof(bufferBoundaries));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sourceObserver, boundariesObserver) = AsyncObserver.Buffer<TSource, TBufferBoundary>(observer);
+
+                var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
+                var boundariesSubscription = await bufferBoundaries.SubscribeSafeAsync(boundariesObserver).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(sourceSubscription, boundariesSubscription);
+            });
+        }
+
+        // REVIEW: This overload is inherited from Rx but arguably a bit esoteric as it doesn't provide context to the closing selector.
+
+        public static IAsyncObservable<IList<TSource>> Buffer<TSource, TBufferClosing>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TBufferClosing>> bufferClosingSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (bufferClosingSelector == null)
+                throw new ArgumentNullException(nameof(bufferClosingSelector));
+
+            return Create<IList<TSource>>(async observer =>
+            {
+                var (sourceObserver, closingDisposable) = await AsyncObserver.Buffer<TSource, TBufferClosing>(observer, bufferClosingSelector).ConfigureAwait(false);
+
+                var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(sourceSubscription, closingDisposable);
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, int count) => Buffer(observer, count, count);
+
+        public static IAsyncObserver<TSource> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, int count, int skip)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+            if (skip <= 0)
+                throw new ArgumentNullException(nameof(skip));
+
+            var queue = new Queue<IList<TSource>>();
+            var n = 0;
+
+            void CreateBuffer() => queue.Enqueue(new List<TSource>());
+
+            CreateBuffer();
+
+            return Create<TSource>(
+                async x =>
+                {
+                    foreach (var buffer in queue)
+                    {
+                        buffer.Add(x);
+                    }
+
+                    var c = n - count + 1;
+
+                    if (c >= 0 && c % skip == 0)
+                    {
+                        var buffer = queue.Dequeue();
+
+                        if (buffer.Count > 0)
+                        {
+                            await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                        }
+                    }
+
+                    n++;
+
+                    if (n % skip == 0)
+                    {
+                        CreateBuffer();
+                    }
+                },
+                ex =>
+                {
+                    while (queue.Count > 0)
+                    {
+                        queue.Dequeue().Clear();
+                    }
+
+                    return observer.OnErrorAsync(ex);
+                },
+                async () =>
+                {
+                    while (queue.Count > 0)
+                    {
+                        var buffer = queue.Dequeue();
+
+                        if (buffer.Count > 0)
+                        {
+                            await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                        }
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan) => Buffer(observer, timeSpan, TaskPoolAsyncScheduler.Default);
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return CoreAsync();
+
+            async Task<(IAsyncObserver<TSource>, IAsyncDisposable)> CoreAsync()
+            {
+                var gate = new AsyncLock();
+
+                var buffer = new List<TSource>();
+
+                var sink = Create<TSource>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            buffer.Add(x);
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (buffer.Count > 0)
+                            {
+                                await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                            }
+
+                            await observer.OnCompletedAsync().ConfigureAwait(false);
+                        }
+                    }
+                );
+
+                var timer = await scheduler.ScheduleAsync(async ct =>
+                {
+                    while (!ct.IsCancellationRequested)
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (buffer.Count > 0)
+                            {
+                                await observer.OnNextAsync(buffer).ConfigureAwait(false);
+
+                                buffer = new List<TSource>();
+                            }
+                        }
+
+                        await scheduler.Delay(timeSpan, ct).RendezVous(scheduler, ct);
+                    }
+                }, timeSpan).ConfigureAwait(false);
+
+                return (sink, timer);
+            };
+        }
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan, TimeSpan timeShift) => Buffer(observer, timeSpan, timeShift, TaskPoolAsyncScheduler.Default);
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan, TimeSpan timeShift, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (timeShift < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeShift));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return CoreAsync();
+
+            async Task<(IAsyncObserver<TSource>, IAsyncDisposable)> CoreAsync()
+            {
+                var gate = new AsyncLock();
+
+                var queue = new Queue<List<TSource>>();
+
+                queue.Enqueue(new List<TSource>());
+
+                var sink = Create<TSource>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            foreach (var buffer in queue)
+                            {
+                                buffer.Add(x);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            while (queue.Count > 0)
+                            {
+                                var buffer = queue.Dequeue();
+
+                                if (buffer.Count > 0)
+                                {
+                                    await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                                }
+                            }
+
+                            await observer.OnCompletedAsync().ConfigureAwait(false);
+                        }
+                    }
+                );
+
+                var nextOpen = timeShift;
+                var nextClose = timeSpan;
+                var totalTime = TimeSpan.Zero;
+
+                var isOpen = false;
+                var isClose = false;
+
+                TimeSpan GetNextDue()
+                {
+                    if (nextOpen == nextClose)
+                    {
+                        isOpen = isClose = true;
+                    }
+                    else if (nextClose < nextOpen)
+                    {
+                        isClose = true;
+                        isOpen = false;
+                    }
+                    else
+                    {
+                        isOpen = true;
+                        isClose = false;
+                    }
+
+                    var newTotalTime = isClose ? nextClose : nextOpen;
+                    var due = newTotalTime - totalTime;
+                    totalTime = newTotalTime;
+
+                    if (isOpen)
+                    {
+                        nextOpen += timeShift;
+                    }
+
+                    if (isClose)
+                    {
+                        nextClose += timeShift;
+                    }
+
+                    return due;
+                }
+
+                var timer = await scheduler.ScheduleAsync(async ct =>
+                {
+                    while (!ct.IsCancellationRequested)
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (isClose)
+                            {
+                                var buffer = queue.Dequeue();
+
+                                if (buffer.Count > 0)
+                                {
+                                    await observer.OnNextAsync(buffer).RendezVous(scheduler, ct);
+                                }
+                            }
+
+                            if (isOpen)
+                            {
+                                queue.Enqueue(new List<TSource>());
+                            }
+                        }
+
+                        await scheduler.Delay(GetNextDue(), ct).RendezVous(scheduler, ct);
+                    }
+                }, GetNextDue()).ConfigureAwait(false);
+
+                return (sink, timer);
+            };
+        }
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan, int count) => Buffer(observer, timeSpan, count, TaskPoolAsyncScheduler.Default);
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource>(IAsyncObserver<IList<TSource>> observer, TimeSpan timeSpan, int count, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (timeSpan < TimeSpan.Zero)
+                throw new ArgumentNullException(nameof(timeSpan));
+            if (count <= 0)
+                throw new ArgumentNullException(nameof(count));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return CoreAsync();
+
+            async Task<(IAsyncObserver<TSource>, IAsyncDisposable)> CoreAsync()
+            {
+                var gate = new AsyncLock();
+
+                var timer = new SerialAsyncDisposable();
+
+                var buffer = new List<TSource>();
+                var n = 0;
+                var id = 0;
+
+                async Task CreateTimerAsync(int timerId)
+                {
+                    var d = await scheduler.ScheduleAsync(async ct =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (timerId == id)
+                            {
+                                await FlushAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }, timeSpan).ConfigureAwait(false);
+
+                    await timer.AssignAsync(d).ConfigureAwait(false);
+                }
+
+                async Task FlushAsync()
+                {
+                    n = 0;
+                    ++id;
+
+                    var res = buffer;
+                    buffer = new List<TSource>();
+                    await observer.OnNextAsync(buffer).ConfigureAwait(false);
+
+                    await CreateTimerAsync(id).ConfigureAwait(false);
+                }
+
+                var sink = Create<TSource>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            buffer.Add(x);
+
+                            if (++n == count)
+                            {
+                                await FlushAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnNextAsync(buffer).ConfigureAwait(false); // NB: We don't check for non-empty in sync Rx either.
+                            await observer.OnCompletedAsync().ConfigureAwait(false);
+                        }
+                    }
+                );
+
+                await CreateTimerAsync(0).ConfigureAwait(false);
+
+                return (sink, timer);
+            };
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncObserver<TBufferBoundary>) Buffer<TSource, TBufferBoundary>(IAsyncObserver<IList<TSource>> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var gate = new AsyncLock();
+
+            var buffer = new List<TSource>();
+
+            return
+                (
+                    Create<TSource>(
+                        async x =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                buffer.Add(x);
+                            }
+                        },
+                        async ex =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                buffer.Clear();
+                                await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            }
+                        },
+                        async () =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    ),
+                    Create<TBufferBoundary>(
+                        async x =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                var oldBuffer = buffer;
+                                buffer = new List<TSource>();
+                                await observer.OnNextAsync(oldBuffer).ConfigureAwait(false);
+                            }
+                        },
+                        async ex =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                buffer.Clear();
+                                await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            }
+                        },
+                        async () =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    )
+                );
+        }
+
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Buffer<TSource, TBufferClosing>(IAsyncObserver<IList<TSource>> observer, Func<IAsyncObservable<TBufferClosing>> bufferClosingSelector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (bufferClosingSelector == null)
+                throw new ArgumentNullException(nameof(bufferClosingSelector));
+
+            return CoreAsync();
+
+            async Task<(IAsyncObserver<TSource>, IAsyncDisposable)> CoreAsync()
+            {
+                var closeSubscription = new SerialAsyncDisposable();
+
+                var gate = new AsyncLock();
+                var queueLock = new AsyncQueueLock();
+
+                var buffer = new List<TSource>();
+
+                async Task CreateBufferCloseAsync()
+                {
+                    var closing = default(IAsyncObservable<TBufferClosing>);
+
+                    try
+                    {
+                        closing = bufferClosingSelector(); // REVIEW: Do we need an async variant?
+                    }
+                    catch (Exception ex)
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            buffer.Clear();
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+
+                        return;
+                    }
+
+                    var closingSubscription = new SingleAssignmentAsyncDisposable();
+                    await closeSubscription.AssignAsync(closingSubscription).ConfigureAwait(false);
+
+                    async Task CloseBufferAsync()
+                    {
+                        await closingSubscription.DisposeAsync().ConfigureAwait(false);
+
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            var oldBuffer = buffer;
+                            buffer = new List<TSource>();
+                            await observer.OnNextAsync(oldBuffer).ConfigureAwait(false);
+                        }
+
+                        await queueLock.WaitAsync(CreateBufferCloseAsync).ConfigureAwait(false);
+                    }
+
+                    var closingObserver =
+                        Create<TBufferClosing>(
+                            x => CloseBufferAsync(),
+                            async ex =>
+                            {
+                                using (await gate.LockAsync().ConfigureAwait(false))
+                                {
+                                    buffer.Clear();
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                }
+                            },
+                            CloseBufferAsync
+                        );
+
+                    var closingSubscriptionInner = await closing.SubscribeSafeAsync(closingObserver).ConfigureAwait(false);
+                    await closingSubscription.AssignAsync(closingSubscriptionInner).ConfigureAwait(false);
+                }
+
+                var sink =
+                    Create<TSource>(
+                        async x =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                buffer.Add(x);
+                            }
+                        },
+                        async ex =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                buffer.Clear();
+                                await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            }
+                        },
+                        async () =>
+                        {
+                            using (await gate.LockAsync().ConfigureAwait(false))
+                            {
+                                await observer.OnNextAsync(buffer).ConfigureAwait(false);
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    );
+
+                await queueLock.WaitAsync(CreateBufferCloseAsync).ConfigureAwait(false);
+
+                return (sink, closeSubscription);
+            }
+        }
+    }
+}

+ 83 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Case.cs

@@ -0,0 +1,83 @@
+// 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.Generic;
+using System.Reactive.Concurrency;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources) => Case(selector, sources, Empty<TResult>());
+
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncScheduler scheduler) => Case(selector, sources, Empty<TResult>(scheduler));
+
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncObservable<TResult> defaultSource)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+            if (defaultSource == null)
+                throw new ArgumentNullException(nameof(defaultSource));
+
+            return Create<TResult>(observer =>
+            {
+                var source = default(IAsyncObservable<TResult>);
+
+                try
+                {
+                    var value = selector();
+
+                    if (!sources.TryGetValue(value, out source))
+                    {
+                        source = defaultSource;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex).SubscribeAsync(observer);
+                }
+
+                return source.SubscribeSafeAsync(observer);
+            });
+        }
+
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<Task<TValue>> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources) => Case(selector, sources, Empty<TResult>());
+
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<Task<TValue>> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncScheduler scheduler) => Case(selector, sources, Empty<TResult>(scheduler));
+
+        public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<Task<TValue>> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncObservable<TResult> defaultSource)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+            if (defaultSource == null)
+                throw new ArgumentNullException(nameof(defaultSource));
+
+            return Create<TResult>(async observer =>
+            {
+                var source = default(IAsyncObservable<TResult>);
+
+                try
+                {
+                    var value = await selector().ConfigureAwait(false);
+
+                    if (!sources.TryGetValue(value, out source))
+                    {
+                        source = defaultSource;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    return await Throw<TResult>(ex).SubscribeAsync(observer).ConfigureAwait(false);
+                }
+
+                return await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+            });
+        }
+    }
+}

+ 28 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Cast.cs

@@ -0,0 +1,28 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TResult> Cast<TSource, TResult>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TResult>(observer => source.SubscribeSafeAsync(AsyncObserver.Cast<TSource, TResult>(observer)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Cast<TSource, TResult>(IAsyncObserver<TResult> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Select<TSource, TResult>(observer, x => (TResult)(object)x);
+        }
+    }
+}

+ 227 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Catch.cs

@@ -0,0 +1,227 @@
+// 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.Generic;
+using System.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    // TODO: Implement tail call behavior to flatten Catch chains.
+
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Catch<TSource, TException>(this IAsyncObservable<TSource> source, Func<TException, IAsyncObservable<TSource>> handler)
+            where TException : Exception
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, inner) = AsyncObserver.Catch(observer, handler);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Catch<TSource, TException>(this IAsyncObservable<TSource> source, Func<TException, Task<IAsyncObservable<TSource>>> handler)
+            where TException : Exception
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, inner) = AsyncObserver.Catch(observer, handler);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Catch<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, inner) = AsyncObserver.Catch(observer, second);
+
+                var subscription = await first.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Catch<TSource>(params IAsyncObservable<TSource>[] sources) => Catch((IEnumerable<IAsyncObservable<TSource>>)sources);
+
+        public static IAsyncObservable<TSource> Catch<TSource>(this IEnumerable<IAsyncObservable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return Create<TSource>(async observer =>
+            {
+                var enumerator = sources.GetEnumerator();
+
+                if (!enumerator.MoveNext())
+                {
+                    return AsyncDisposable.Nop; // REVIEW: Is Never behavior right here?
+                }
+
+                var source = enumerator.Current;
+
+                var (sink, inner) = AsyncObserver.Catch(observer, enumerator);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Catch<TSource, TException>(IAsyncObserver<TSource> observer, Func<TException, IAsyncObservable<TSource>> handler)
+            where TException : Exception
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            return Catch<TSource, TException>(observer, ex => Task.FromResult(handler(ex)));
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Catch<TSource, TException>(IAsyncObserver<TSource> observer, Func<TException, Task<IAsyncObservable<TSource>>> handler)
+            where TException : Exception
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            var subscription = new SingleAssignmentAsyncDisposable();
+
+            var sink = Create<TSource>(
+                observer.OnNextAsync,
+                async ex =>
+                {
+                    if (ex is TException error)
+                    {
+                        IAsyncObservable<TSource> handlerObservable;
+
+                        try
+                        {
+                            handlerObservable = await handler(error).ConfigureAwait(false);
+                        }
+                        catch (Exception err)
+                        {
+                            await observer.OnErrorAsync(err).ConfigureAwait(false);
+                            return;
+                        }
+
+                        var handlerSubscription = await handlerObservable.SubscribeSafeAsync(observer).ConfigureAwait(false);
+
+                        await subscription.AssignAsync(handlerSubscription).ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                observer.OnCompletedAsync
+            );
+
+            return (sink, subscription);
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Catch<TSource>(IAsyncObserver<TSource> observer, IAsyncObservable<TSource> second)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            var subscription = new SingleAssignmentAsyncDisposable();
+
+            var sink = Create<TSource>(
+                observer.OnNextAsync,
+                async ex =>
+                {
+                    var secondSubscription = await second.SubscribeSafeAsync(observer).ConfigureAwait(false);
+
+                    await subscription.AssignAsync(secondSubscription).ConfigureAwait(false);
+                },
+                observer.OnCompletedAsync
+            );
+
+            return (sink, subscription);
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Catch<TSource>(IAsyncObserver<TSource> observer, IEnumerator<IAsyncObservable<TSource>> handlers)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (handlers == null)
+                throw new ArgumentNullException(nameof(handlers));
+
+            var innerSubscription = new SerialAsyncDisposable();
+
+            IAsyncObserver<TSource> GetSink() =>
+                Create<TSource>(
+                    observer.OnNextAsync,
+                    async ex =>
+                    {
+                        var handler = default(IAsyncObservable<TSource>);
+
+                        try
+                        {
+                            if (handlers.MoveNext())
+                            {
+                                handler = handlers.Current;
+                            }
+                        }
+                        catch (Exception err)
+                        {
+                            await observer.OnErrorAsync(err).ConfigureAwait(false);
+                            return;
+                        }
+
+                        if (handler == null)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false); // REVIEW: Is Throw behavior right here?
+                            return;
+                        }
+
+                        var handlerSubscription = await handler.SubscribeSafeAsync(GetSink()).ConfigureAwait(false);
+
+                        await innerSubscription.AssignAsync(handlerSubscription).ConfigureAwait(false);
+                    },
+                    observer.OnCompletedAsync
+                );
+
+            var disposeEnumerator = AsyncDisposable.Create(() =>
+            {
+                handlers.Dispose();
+                return Task.CompletedTask;
+            });
+
+            var subscription = StableCompositeAsyncDisposable.Create(innerSubscription, disposeEnumerator);
+
+            return (GetSink(), subscription);
+        }
+    }
+}

+ 14662 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/CombineLatest.Generated.cs

@@ -0,0 +1,14662 @@
+// 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.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<(T1, T2)> CombineLatest<T1, T2>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+
+            return Create<(T1, T2)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, Func<T1, T2, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, Func<T1, T2, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3)> CombineLatest<T1, T2, T3>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+
+            return Create<(T1, T2, T3)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, Func<T1, T2, T3, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, Func<T1, T2, T3, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4)> CombineLatest<T1, T2, T3, T4>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+
+            return Create<(T1, T2, T3, T4)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, Func<T1, T2, T3, T4, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, Func<T1, T2, T3, T4, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5)> CombineLatest<T1, T2, T3, T4, T5>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+
+            return Create<(T1, T2, T3, T4, T5)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, Func<T1, T2, T3, T4, T5, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6)> CombineLatest<T1, T2, T3, T4, T5, T6>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+
+            return Create<(T1, T2, T3, T4, T5, T6)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, Func<T1, T2, T3, T4, T5, T6, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7)> CombineLatest<T1, T2, T3, T4, T5, T6, T7>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14, IAsyncObservable<T15> source15)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+            if (source15 == null)
+                throw new ArgumentNullException(nameof(source15));
+
+            return Create<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14, observer15) = AsyncObserver.CombineLatest(observer);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub15 = source15.SubscribeSafeAsync(observer15).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14, IAsyncObservable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+            if (source15 == null)
+                throw new ArgumentNullException(nameof(source15));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14, observer15) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub15 = source15.SubscribeSafeAsync(observer15).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, IAsyncObservable<T8> source8, IAsyncObservable<T9> source9, IAsyncObservable<T10> source10, IAsyncObservable<T11> source11, IAsyncObservable<T12> source12, IAsyncObservable<T13> source13, IAsyncObservable<T14> source14, IAsyncObservable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, Task<TResult>> selector)
+        {
+            if (source1 == null)
+                throw new ArgumentNullException(nameof(source1));
+            if (source2 == null)
+                throw new ArgumentNullException(nameof(source2));
+            if (source3 == null)
+                throw new ArgumentNullException(nameof(source3));
+            if (source4 == null)
+                throw new ArgumentNullException(nameof(source4));
+            if (source5 == null)
+                throw new ArgumentNullException(nameof(source5));
+            if (source6 == null)
+                throw new ArgumentNullException(nameof(source6));
+            if (source7 == null)
+                throw new ArgumentNullException(nameof(source7));
+            if (source8 == null)
+                throw new ArgumentNullException(nameof(source8));
+            if (source9 == null)
+                throw new ArgumentNullException(nameof(source9));
+            if (source10 == null)
+                throw new ArgumentNullException(nameof(source10));
+            if (source11 == null)
+                throw new ArgumentNullException(nameof(source11));
+            if (source12 == null)
+                throw new ArgumentNullException(nameof(source12));
+            if (source13 == null)
+                throw new ArgumentNullException(nameof(source13));
+            if (source14 == null)
+                throw new ArgumentNullException(nameof(source14));
+            if (source15 == null)
+                throw new ArgumentNullException(nameof(source15));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14, observer15) = AsyncObserver.CombineLatest(observer, selector);
+
+                var sub1 = source1.SubscribeSafeAsync(observer1).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub2 = source2.SubscribeSafeAsync(observer2).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub3 = source3.SubscribeSafeAsync(observer3).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub4 = source4.SubscribeSafeAsync(observer4).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub5 = source5.SubscribeSafeAsync(observer5).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub6 = source6.SubscribeSafeAsync(observer6).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub7 = source7.SubscribeSafeAsync(observer7).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub8 = source8.SubscribeSafeAsync(observer8).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub9 = source9.SubscribeSafeAsync(observer9).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub10 = source10.SubscribeSafeAsync(observer10).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub11 = source11.SubscribeSafeAsync(observer11).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub12 = source12.SubscribeSafeAsync(observer12).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub13 = source13.SubscribeSafeAsync(observer13).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub14 = source14.SubscribeSafeAsync(observer14).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+                var sub15 = source15.SubscribeSafeAsync(observer15).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+
+                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, sub9, sub10, sub11, sub12, sub13, sub14, sub15).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+    }
+
+    partial class AsyncObserver
+    {
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>) CombineLatest<T1, T2>(IAsyncObserver<(T1, T2)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2)).ConfigureAwait(false);
+                            }
+                            else if (isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2)).ConfigureAwait(false);
+                            }
+                            else if (isDone1)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>) CombineLatest<T1, T2, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, TResult>(observer, (x1, x2) => Task.FromResult(selector(x1, x2)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>) CombineLatest<T1, T2, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>) CombineLatest<T1, T2, T3>(IAsyncObserver<(T1, T2, T3)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>) CombineLatest<T1, T2, T3, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, TResult>(observer, (x1, x2, x3) => Task.FromResult(selector(x1, x2, x3)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>) CombineLatest<T1, T2, T3, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>) CombineLatest<T1, T2, T3, T4>(IAsyncObserver<(T1, T2, T3, T4)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>) CombineLatest<T1, T2, T3, T4, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, TResult>(observer, (x1, x2, x3, x4) => Task.FromResult(selector(x1, x2, x3, x4)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>) CombineLatest<T1, T2, T3, T4, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>) CombineLatest<T1, T2, T3, T4, T5>(IAsyncObserver<(T1, T2, T3, T4, T5)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>) CombineLatest<T1, T2, T3, T4, T5, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, TResult>(observer, (x1, x2, x3, x4, x5) => Task.FromResult(selector(x1, x2, x3, x4, x5)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>) CombineLatest<T1, T2, T3, T4, T5, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>) CombineLatest<T1, T2, T3, T4, T5, T6>(IAsyncObserver<(T1, T2, T3, T4, T5, T6)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>) CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(observer, (x1, x2, x3, x4, x5, x6) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>) CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>) CombineLatest<T1, T2, T3, T4, T5, T6, T7>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+            bool hasValue14 = false;
+            bool isDone14 = false;
+            T14 latestValue14 = default(T14);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T14>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue14)
+                            {
+                                hasValue14 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue14 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone14 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+            bool hasValue14 = false;
+            bool isDone14 = false;
+            T14 latestValue14 = default(T14);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T14>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue14)
+                            {
+                                hasValue14 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14;
+                            }
+
+                            latestValue14 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone14 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>, IAsyncObserver<T15>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(IAsyncObserver<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+            bool hasValue14 = false;
+            bool isDone14 = false;
+            T14 latestValue14 = default(T14);
+            bool hasValue15 = false;
+            bool isDone15 = false;
+            T15 latestValue15 = default(T15);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T14>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue14)
+                            {
+                                hasValue14 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue14 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone14 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T15>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue15)
+                            {
+                                hasValue15 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue15 = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15)).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone15 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>, IAsyncObserver<T15>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(observer, (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) => Task.FromResult(selector(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)));
+        }
+
+        public static (IAsyncObserver<T1>, IAsyncObserver<T2>, IAsyncObserver<T3>, IAsyncObserver<T4>, IAsyncObserver<T5>, IAsyncObserver<T6>, IAsyncObserver<T7>, IAsyncObserver<T8>, IAsyncObserver<T9>, IAsyncObserver<T10>, IAsyncObserver<T11>, IAsyncObserver<T12>, IAsyncObserver<T13>, IAsyncObserver<T14>, IAsyncObserver<T15>) CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+            bool hasValue1 = false;
+            bool isDone1 = false;
+            T1 latestValue1 = default(T1);
+            bool hasValue2 = false;
+            bool isDone2 = false;
+            T2 latestValue2 = default(T2);
+            bool hasValue3 = false;
+            bool isDone3 = false;
+            T3 latestValue3 = default(T3);
+            bool hasValue4 = false;
+            bool isDone4 = false;
+            T4 latestValue4 = default(T4);
+            bool hasValue5 = false;
+            bool isDone5 = false;
+            T5 latestValue5 = default(T5);
+            bool hasValue6 = false;
+            bool isDone6 = false;
+            T6 latestValue6 = default(T6);
+            bool hasValue7 = false;
+            bool isDone7 = false;
+            T7 latestValue7 = default(T7);
+            bool hasValue8 = false;
+            bool isDone8 = false;
+            T8 latestValue8 = default(T8);
+            bool hasValue9 = false;
+            bool isDone9 = false;
+            T9 latestValue9 = default(T9);
+            bool hasValue10 = false;
+            bool isDone10 = false;
+            T10 latestValue10 = default(T10);
+            bool hasValue11 = false;
+            bool isDone11 = false;
+            T11 latestValue11 = default(T11);
+            bool hasValue12 = false;
+            bool isDone12 = false;
+            T12 latestValue12 = default(T12);
+            bool hasValue13 = false;
+            bool isDone13 = false;
+            T13 latestValue13 = default(T13);
+            bool hasValue14 = false;
+            bool isDone14 = false;
+            T14 latestValue14 = default(T14);
+            bool hasValue15 = false;
+            bool isDone15 = false;
+            T15 latestValue15 = default(T15);
+
+            var gate = new AsyncLock();
+
+            return
+            (
+                Create<T1>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue1)
+                            {
+                                hasValue1 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue1 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone1 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T2>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue2)
+                            {
+                                hasValue2 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue2 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone2 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T3>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue3)
+                            {
+                                hasValue3 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue3 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone3 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T4>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue4)
+                            {
+                                hasValue4 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue4 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone4 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T5>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue5)
+                            {
+                                hasValue5 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue5 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone5 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T6>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue6)
+                            {
+                                hasValue6 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue6 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone6 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T7>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue7)
+                            {
+                                hasValue7 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue7 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone7 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T8>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue8)
+                            {
+                                hasValue8 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue8 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone8 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T9>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue9)
+                            {
+                                hasValue9 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue9 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone9 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T10>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue10)
+                            {
+                                hasValue10 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue10 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone10 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T11>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue11)
+                            {
+                                hasValue11 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue11 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone11 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T12>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue12)
+                            {
+                                hasValue12 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue12 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone12 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T13>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue13)
+                            {
+                                hasValue13 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue13 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone13 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T14>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue14)
+                            {
+                                hasValue14 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue14 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone14 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                ),
+                Create<T15>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue15)
+                            {
+                                hasValue15 = true;
+                                allHasValue = hasValue1 && hasValue2 && hasValue3 && hasValue4 && hasValue5 && hasValue6 && hasValue7 && hasValue8 && hasValue9 && hasValue10 && hasValue11 && hasValue12 && hasValue13 && hasValue14 && hasValue15;
+                            }
+
+                            latestValue15 = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(latestValue1, latestValue2, latestValue3, latestValue4, latestValue5, latestValue6, latestValue7, latestValue8, latestValue9, latestValue10, latestValue11, latestValue12, latestValue13, latestValue14, latestValue15).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone15 = true;
+
+                            if (isDone1 && isDone2 && isDone3 && isDone4 && isDone5 && isDone6 && isDone7 && isDone8 && isDone9 && isDone10 && isDone11 && isDone12 && isDone13 && isDone14 && isDone15)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )
+            );
+        }
+
+    }
+}

+ 323 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/CombineLatest.Generated.tt

@@ -0,0 +1,323 @@
+// 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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+<#
+for (var i = 2; i <= 15; i++)
+{
+    var genPars = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "TResult" }));
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
+    var args = string.Join(", ", Enumerable.Range(1, i).Select(j => "IAsyncObservable<T" + j + "> source" + j));
+    var obs = "(" + string.Join(", ", Enumerable.Range(1, i).Select(j => "observer" + j)) + ")";
+    var tuple = "(" + genArgs + ")";
+#>
+        public static IAsyncObservable<<#=tuple#>> CombineLatest<<#=genArgs#>>(this <#=args#>)
+        {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            if (source<#=j#> == null)
+                throw new ArgumentNullException(nameof(source<#=j#>));
+<#
+}
+#>
+
+            return Create<<#=tuple#>>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var <#=obs#> = AsyncObserver.CombineLatest(observer);
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                var sub<#=j#> = source<#=j#>.SubscribeSafeAsync(observer<#=j#>).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+<#
+}
+#>
+
+                await Task.WhenAll(<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "sub" + j))#>).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<<#=genPars#>>(this <#=args#>, Func<<#=genArgs#>, TResult> selector)
+        {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            if (source<#=j#> == null)
+                throw new ArgumentNullException(nameof(source<#=j#>));
+<#
+}
+#>
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var <#=obs#> = AsyncObserver.CombineLatest(observer, selector);
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                var sub<#=j#> = source<#=j#>.SubscribeSafeAsync(observer<#=j#>).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+<#
+}
+#>
+
+                await Task.WhenAll(<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "sub" + j))#>).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TResult> CombineLatest<<#=genPars#>>(this <#=args#>, Func<<#=genArgs#>, Task<TResult>> selector)
+        {
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            if (source<#=j#> == null)
+                throw new ArgumentNullException(nameof(source<#=j#>));
+<#
+}
+#>
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create<TResult>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var <#=obs#> = AsyncObserver.CombineLatest(observer, selector);
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                var sub<#=j#> = source<#=j#>.SubscribeSafeAsync(observer<#=j#>).ContinueWith(disposable => d.AddAsync(disposable.Result)).Unwrap();
+<#
+}
+#>
+
+                await Task.WhenAll(<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "sub" + j))#>).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+<#
+}
+#>
+    }
+
+    partial class AsyncObserver
+    {
+<#
+for (var i = 2; i <= 15; i++)
+{
+    var res = "(" + string.Join(", ", Enumerable.Range(1, i).Select(j => "IAsyncObserver<T" + j + ">")) + ")";
+    var genPars = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "TResult" }));
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
+    var tuple = "(" + genArgs + ")";
+#>
+        public static <#=res#> CombineLatest<<#=genArgs#>>(IAsyncObserver<<#=tuple#>> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            bool allHasValue = false;
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            bool hasValue<#=j#> = false;
+            bool isDone<#=j#> = false;
+            T<#=j#> latestValue<#=j#> = default(T<#=j#>);
+<#
+}
+#>
+
+            var gate = new AsyncLock();
+
+            return
+            (
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                Create<T<#=j#>>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue<#=j#>)
+                            {
+                                hasValue<#=j#> = true;
+                                allHasValue = <#=string.Join(" && ", Enumerable.Range(1, i).Select(k => "hasValue" + k))#>;
+                            }
+
+                            latestValue<#=j#> = x;
+
+                            if (allHasValue)
+                            {
+                                await observer.OnNextAsync((<#=string.Join(", ", Enumerable.Range(1, i).Select(k => "latestValue" + k))#>)).ConfigureAwait(false);
+                            }
+                            else if (<#=string.Join(" && ", Enumerable.Range(1, i).Where(k => k != j).Select(k => "isDone" + k))#>)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone<#=j#> = true;
+
+                            if (<#=string.Join(" && ", Enumerable.Range(1, i).Select(k => "isDone" + k))#>)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )<#=(j < i ? "," : "")#>
+<#
+}
+#>
+            );
+        }
+
+        public static <#=res#> CombineLatest<<#=genPars#>>(IAsyncObserver<TResult> observer, Func<<#=genArgs#>, TResult> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return CombineLatest<<#=genPars#>>(observer, (<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "x" + j))#>) => Task.FromResult(selector(<#=string.Join(", ", Enumerable.Range(1, i).Select(j => "x" + j))#>)));
+        }
+
+        public static <#=res#> CombineLatest<<#=genPars#>>(IAsyncObserver<TResult> observer, Func<<#=genArgs#>, Task<TResult>> selector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            bool allHasValue = false;
+
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+            bool hasValue<#=j#> = false;
+            bool isDone<#=j#> = false;
+            T<#=j#> latestValue<#=j#> = default(T<#=j#>);
+<#
+}
+#>
+
+            var gate = new AsyncLock();
+
+            return
+            (
+<#
+for (var j = 1; j <= i; j++)
+{
+#>
+                Create<T<#=j#>>(
+                    async x =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            if (!hasValue<#=j#>)
+                            {
+                                hasValue<#=j#> = true;
+                                allHasValue = <#=string.Join(" && ", Enumerable.Range(1, i).Select(k => "hasValue" + k))#>;
+                            }
+
+                            latestValue<#=j#> = x;
+
+                            if (allHasValue)
+                            {
+                                TResult res;
+                                try
+                                {
+                                    res = await selector(<#=string.Join(", ", Enumerable.Range(1, i).Select(k => "latestValue" + k))#>).ConfigureAwait(false);
+                                }
+                                catch (Exception ex)
+                                {
+                                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                                    return;
+                                }
+
+                                await observer.OnNextAsync(res).ConfigureAwait(false);
+                            }
+                            else if (<#=string.Join(" && ", Enumerable.Range(1, i).Where(k => k != j).Select(k => "isDone" + k))#>)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        using (await gate.LockAsync().ConfigureAwait(false))
+                        {
+                            isDone<#=j#> = true;
+
+                            if (<#=string.Join(" && ", Enumerable.Range(1, i).Select(k => "isDone" + k))#>)
+                            {
+                                await observer.OnCompletedAsync().ConfigureAwait(false);
+                            }
+                        }
+                    }
+                )<#=(j < i ? "," : "")#>
+<#
+}
+#>
+            );
+        }
+
+<#
+}
+#>
+    }
+}

+ 137 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Concat.cs

@@ -0,0 +1,137 @@
+// 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.Generic;
+using System.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    // TODO: Implement tail call behavior to flatten Concat chains.
+
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Concat<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, inner) = AsyncObserver.Concat(observer, second);
+
+                var subscription = await first.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Concat<TSource>(params IAsyncObservable<TSource>[] sources) => Concat((IEnumerable<IAsyncObservable<TSource>>)sources);
+
+        public static IAsyncObservable<TSource> Concat<TSource>(this IEnumerable<IAsyncObservable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return Create<TSource>(async observer =>
+            {
+                var enumerator = sources.GetEnumerator();
+
+                if (!enumerator.MoveNext())
+                {
+                    return AsyncDisposable.Nop; // REVIEW: Is Never behavior right here?
+                }
+
+                var source = enumerator.Current;
+
+                var (sink, inner) = AsyncObserver.Concat(observer, enumerator);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, inner);
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Concat<TSource>(IAsyncObserver<TSource> observer, IAsyncObservable<TSource> second)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            var subscription = new SingleAssignmentAsyncDisposable();
+
+            var sink = Create<TSource>(
+                observer.OnNextAsync,
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    var secondSubscription = await second.SubscribeSafeAsync(observer).ConfigureAwait(false);
+
+                    await subscription.AssignAsync(secondSubscription).ConfigureAwait(false);
+                }
+            );
+
+            return (sink, subscription);
+        }
+
+        public static (IAsyncObserver<TSource>, IAsyncDisposable) Concat<TSource>(IAsyncObserver<TSource> observer, IEnumerator<IAsyncObservable<TSource>> handlers)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (handlers == null)
+                throw new ArgumentNullException(nameof(handlers));
+
+            var innerSubscription = new SerialAsyncDisposable();
+
+            IAsyncObserver<TSource> GetSink() =>
+                Create<TSource>(
+                    observer.OnNextAsync,
+                    observer.OnErrorAsync,
+                    async () =>
+                    {
+                        var next = default(IAsyncObservable<TSource>);
+
+                        try
+                        {
+                            if (handlers.MoveNext())
+                            {
+                                next = handlers.Current;
+                            }
+                        }
+                        catch (Exception err)
+                        {
+                            await observer.OnErrorAsync(err).ConfigureAwait(false);
+                            return;
+                        }
+
+                        if (next == null)
+                        {
+                            await observer.OnCompletedAsync().ConfigureAwait(false); // REVIEW: Is Empty behavior right here?
+                            return;
+                        }
+
+                        var nextSubscription = await next.SubscribeSafeAsync(GetSink()).ConfigureAwait(false);
+
+                        await innerSubscription.AssignAsync(nextSubscription).ConfigureAwait(false);
+                    }
+                );
+
+            var disposeEnumerator = AsyncDisposable.Create(() =>
+            {
+                handlers.Dispose();
+                return Task.CompletedTask;
+            });
+
+            var subscription = StableCompositeAsyncDisposable.Create(innerSubscription, disposeEnumerator);
+
+            return (GetSink(), subscription);
+        }
+    }
+}

+ 76 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Contains.cs

@@ -0,0 +1,76 @@
+// 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.Generic;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<bool> Contains<TSource>(this IAsyncObservable<TSource> source, TSource element)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.Contains(observer, element)));
+        }
+
+        public static IAsyncObservable<bool> Contains<TSource>(this IAsyncObservable<TSource> source, TSource element, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<bool>(observer => source.SubscribeSafeAsync(AsyncObserver.Contains(observer, element, comparer)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Contains<TSource>(IAsyncObserver<bool> observer, TSource element)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Contains(observer, element, EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncObserver<TSource> Contains<TSource>(IAsyncObserver<bool> observer, TSource element, IEqualityComparer<TSource> comparer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var equals = false;
+                    try
+                    {
+                        equals = comparer.Equals(x, element);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (equals)
+                    {
+                        await observer.OnNextAsync(true).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(false).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 94 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Count.cs

@@ -0,0 +1,94 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<int> Count<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<int>(observer => source.SubscribeSafeAsync(AsyncObserver.Count<TSource>(observer)));
+        }
+
+        public static IAsyncObservable<int> Count<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<int>(observer => source.SubscribeSafeAsync(AsyncObserver.Count(observer, predicate)));
+        }
+
+        public static IAsyncObservable<int> Count<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<int>(observer => source.SubscribeSafeAsync(AsyncObserver.Count(observer, predicate)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Count<TSource>(IAsyncObserver<int> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var count = 0;
+
+            return Create<TSource>(
+                async x =>
+                {
+                    try
+                    {
+                        checked
+                        {
+                            count++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(count).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Count<TSource>(IAsyncObserver<int> observer, Func<TSource, bool> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(Count<TSource>(observer), predicate);
+        }
+
+        public static IAsyncObserver<TSource> Count<TSource>(IAsyncObserver<int> observer, Func<TSource, Task<bool>> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(Count<TSource>(observer), predicate);
+        }
+    }
+}

+ 62 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DefaultIfEmpty.cs

@@ -0,0 +1,62 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> DefaultIfEmpty<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DefaultIfEmpty<TSource>(observer)));
+        }
+
+        public static IAsyncObservable<TSource> DefaultIfEmpty<TSource>(this IAsyncObservable<TSource> source, TSource defaultValue)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DefaultIfEmpty<TSource>(observer, defaultValue)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> DefaultIfEmpty<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return DefaultIfEmpty(observer, default(TSource));
+        }
+
+        public static IAsyncObserver<TSource> DefaultIfEmpty<TSource>(IAsyncObserver<TSource> observer, TSource defaultValue)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            var hasValue = false;
+
+            return Create<TSource>(
+                x =>
+                {
+                    hasValue = true;
+                    return observer.OnNextAsync(x);
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    if (!hasValue)
+                    {
+                        await observer.OnNextAsync(defaultValue).ConfigureAwait(false);
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 56 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Defer.cs

@@ -0,0 +1,56 @@
+// 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.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Defer<TSource>(Func<IAsyncObservable<TSource>> observableFactory)
+        {
+            if (observableFactory == null)
+                throw new ArgumentNullException(nameof(observableFactory));
+
+            return Defer(() => Task.FromResult(observableFactory()));
+        }
+
+        public static IAsyncObservable<TSource> DeferAsync<TSource>(Func<Task<IAsyncObservable<TSource>>> observableFactory) => Defer(observableFactory);
+
+        public static IAsyncObservable<TSource> Defer<TSource>(Func<Task<IAsyncObservable<TSource>>> observableFactory)
+        {
+            if (observableFactory == null)
+                throw new ArgumentNullException(nameof(observableFactory));
+
+            return Create<TSource>(async observer =>
+            {
+                var source = default(IAsyncObservable<TSource>);
+
+                try
+                {
+                    source = await observableFactory().ConfigureAwait(false);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return AsyncDisposable.Nop;
+                }
+
+                return await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+            });
+        }
+
+        public static IAsyncObservable<TSource> DeferAsync<TSource>(Func<CancellationToken, Task<IAsyncObservable<TSource>>> observableFactory) => DeferAsync(observableFactory);
+
+        public static IAsyncObservable<TSource> Defer<TSource>(Func<CancellationToken, Task<IAsyncObservable<TSource>>> observableFactory)
+        {
+            if (observableFactory == null)
+                throw new ArgumentNullException(nameof(observableFactory));
+
+            return StartAsync(observableFactory).Merge();
+        }
+    }
+}

+ 138 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Delay.cs

@@ -0,0 +1,138 @@
+// 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.Generic;
+using System.Reactive.Concurrency;
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    // TODO: Add overloads with DateTimeOffset and with duration selector.
+
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Delay<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, drain) = await AsyncObserver.Delay(observer, dueTime).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, drain);
+            });
+        }
+
+        public static IAsyncObservable<TSource> Delay<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<TSource>(async observer =>
+            {
+                var (sink, drain) = await AsyncObserver.Delay(observer, dueTime, scheduler).ConfigureAwait(false);
+
+                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
+
+                return StableCompositeAsyncDisposable.Create(subscription, drain);
+            });
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Delay<TSource>(this IAsyncObserver<TSource> observer, TimeSpan dueTime)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Delay(observer, dueTime, TaskPoolAsyncScheduler.Default);
+        }
+
+        public static async Task<(IAsyncObserver<TSource>, IAsyncDisposable)> Delay<TSource>(this IAsyncObserver<TSource> observer, TimeSpan dueTime, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            // TODO: Use stopwatch functionality.
+
+            var start = scheduler.Now;
+
+            var semaphore = new SemaphoreSlim(0);
+
+            var gate = new AsyncLock();
+
+            var queue = new Queue<TimeInterval<TSource>>();
+            var isDone = false;
+
+            var drain = await scheduler.ScheduleAsync(async ct =>
+            {
+                while (!ct.IsCancellationRequested)
+                {
+                    await semaphore.WaitAsync(ct).RendezVous(scheduler, ct);
+
+                    if (queue.Count > 0)
+                    {
+                        var next = queue.Dequeue();
+
+                        var nextDueTime = start + next.Interval + dueTime;
+                        var delay = nextDueTime - scheduler.Now;
+
+                        await scheduler.Delay(delay, ct).RendezVous(scheduler, ct);
+
+                        await observer.OnNextAsync(next.Value).RendezVous(scheduler, ct);
+                    }
+
+                    if (queue.Count == 0 && isDone)
+                    {
+                        await observer.OnCompletedAsync().RendezVous(scheduler, ct);
+                        break;
+                    }
+                }
+            }).ConfigureAwait(false);
+
+            var sink = Create<TSource>(
+                async x =>
+                {
+                    var time = scheduler.Now;
+                    var delay = time - start;
+
+                    using (await gate.LockAsync().ConfigureAwait(false))
+                    {
+                        queue.Enqueue(new TimeInterval<TSource>(x, delay));
+                    }
+
+                    semaphore.Release(1);
+                },
+                async ex =>
+                {
+                    using (await gate.LockAsync().ConfigureAwait(false))
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    }
+                },
+                async () =>
+                {
+                    using (await gate.LockAsync().ConfigureAwait(false))
+                    {
+                        isDone = true;
+                    }
+
+                    semaphore.Release(1);
+                }
+            );
+
+            return (sink, drain);
+        }
+    }
+}

+ 74 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DelaySubscription.cs

@@ -0,0 +1,74 @@
+// 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.Reactive.Concurrency;
+using System.Reactive.Disposables;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return DelaySubscription(source, dueTime, TaskPoolAsyncScheduler.Default);
+        }
+
+        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<TSource>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var task = await scheduler.ScheduleAsync(async ct =>
+                {
+                    var inner = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+                    await d.AddAsync(inner).ConfigureAwait(false);
+                }, dueTime).ConfigureAwait(false);
+
+                await d.AddAsync(task).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+
+        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, DateTimeOffset dueTime)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return DelaySubscription(source, dueTime, TaskPoolAsyncScheduler.Default);
+        }
+
+        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, DateTimeOffset dueTime, IAsyncScheduler scheduler)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<TSource>(async observer =>
+            {
+                var d = new CompositeAsyncDisposable();
+
+                var task = await scheduler.ScheduleAsync(async ct =>
+                {
+                    var inner = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+                    await d.AddAsync(inner).ConfigureAwait(false);
+                }, dueTime).ConfigureAwait(false);
+
+                await d.AddAsync(task).ConfigureAwait(false);
+
+                return d;
+            });
+        }
+    }
+}

+ 32 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Dematerialize.cs

@@ -0,0 +1,32 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Dematerialize<TSource>(this IAsyncObservable<Notification<TSource>> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Dematerialize(observer)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<Notification<TSource>> Dematerialize<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<Notification<TSource>>(
+                n => n.AcceptAsync(observer),
+                observer.OnErrorAsync,
+                observer.OnCompletedAsync
+            );
+        }
+    }
+}

+ 74 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Distinct.cs

@@ -0,0 +1,74 @@
+// 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.Generic;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Distinct<TSource>(IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Distinct(observer)));
+        }
+
+        public static IAsyncObservable<TSource> Distinct<TSource>(IAsyncObservable<TSource> source, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.Distinct(observer, comparer)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Distinct<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Distinct(observer, EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncObserver<TSource> Distinct<TSource>(IAsyncObserver<TSource> observer, IEqualityComparer<TSource> comparer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            var set = new HashSet<TSource>(comparer);
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var added = false;
+
+                    try
+                    {
+                        added = set.Add(x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (added)
+                    {
+                        await observer.OnNextAsync(x).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                observer.OnCompletedAsync
+            );
+        }
+    }
+}

+ 225 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DistinctUntilChanged.cs

@@ -0,0 +1,225 @@
+// 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.Generic;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource>(IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer)));
+        }
+
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource>(IAsyncObservable<TSource> source, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, comparer)));
+        }
+
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, keySelector)));
+        }
+
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObservable<TSource> source, Func<TSource, Task<TKey>> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, keySelector)));
+        }
+
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, keySelector, comparer)));
+        }
+
+        public static IAsyncObservable<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObservable<TSource> source, Func<TSource, Task<TKey>> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, keySelector, comparer)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return DistinctUntilChanged(observer, x => x, EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource>(IAsyncObserver<TSource> observer, IEqualityComparer<TSource> comparer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return DistinctUntilChanged(observer, x => x, comparer);
+        }
+
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObserver<TSource> observer, Func<TSource, TKey> keySelector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return DistinctUntilChanged(observer, keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObserver<TSource> observer, Func<TSource, Task<TKey>> keySelector)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return DistinctUntilChanged(observer, keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObserver<TSource> observer, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            var hasCurrentKey = false;
+            var currentKey = default(TKey);
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var key = default(TKey);
+
+                    try
+                    {
+                        key = keySelector(x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    var equals = default(bool);
+
+                    if (hasCurrentKey)
+                    {
+                        try
+                        {
+                            equals = comparer.Equals(currentKey, key);
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+                    }
+
+                    if (!hasCurrentKey || !equals)
+                    {
+                        hasCurrentKey = true;
+                        currentKey = key;
+
+                        await observer.OnNextAsync(x).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                observer.OnCompletedAsync
+            );
+        }
+
+        public static IAsyncObserver<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObserver<TSource> observer, Func<TSource, Task<TKey>> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            var hasCurrentKey = false;
+            var currentKey = default(TKey);
+
+            return Create<TSource>(
+                async x =>
+                {
+                    var key = default(TKey);
+
+                    try
+                    {
+                        key = await keySelector(x).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    var equals = default(bool);
+
+                    if (hasCurrentKey)
+                    {
+                        try
+                        {
+                            equals = comparer.Equals(currentKey, key);
+                        }
+                        catch (Exception ex)
+                        {
+                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                            return;
+                        }
+                    }
+
+                    if (!hasCurrentKey || !equals)
+                    {
+                        hasCurrentKey = true;
+                        currentKey = key;
+
+                        await observer.OnNextAsync(x).ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                observer.OnCompletedAsync
+            );
+        }
+    }
+}

+ 316 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Do.cs

@@ -0,0 +1,316 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, IObserver<TSource> observer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, observer)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onNext)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action<Exception> onError)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onError)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onCompleted)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onNext, onError, onCompleted)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, IAsyncObserver<TSource> observer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, observer)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onNext)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Func<Exception, Task> onError)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onError)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Func<Task> onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onCompleted)));
+        }
+
+        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Create<TSource>(target => source.SubscribeSafeAsync(AsyncObserver.Do(target, onNext, onError, onCompleted)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, IAsyncObserver<TSource> witness)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (witness == null)
+                throw new ArgumentNullException(nameof(witness));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    try
+                    {
+                        await witness.OnNextAsync(x).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                },
+                async error =>
+                {
+                    try
+                    {
+                        await witness.OnErrorAsync(error).ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnErrorAsync(error).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    try
+                    {
+                        await witness.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<TSource, Task> onNext)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return Do(observer, Create(onNext));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<Exception, Task> onError)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return Do(observer, Create<TSource>(_ => Task.CompletedTask, onError, () => Task.CompletedTask));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<Task> onCompleted)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Do(observer, Create<TSource>(_ => Task.CompletedTask, _ => Task.CompletedTask, onCompleted));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<TSource, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Do(observer, Create(onNext, onError, onCompleted));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, IObserver<TSource> witness)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (witness == null)
+                throw new ArgumentNullException(nameof(witness));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    try
+                    {
+                        witness.OnNext(x);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                },
+                async error =>
+                {
+                    try
+                    {
+                        witness.OnError(error);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnErrorAsync(error).ConfigureAwait(false);
+                },
+                async () =>
+                {
+                    try
+                    {
+                        witness.OnCompleted();
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Action<TSource> onNext)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return Do(observer, x => { onNext(x); return Task.CompletedTask; });
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Action<Exception> onError)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return Do(observer, Create<TSource>(_ => Task.CompletedTask, ex => { onError(ex); return Task.CompletedTask; }, () => Task.CompletedTask));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Action onCompleted)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Do(observer, Create<TSource>(_ => Task.CompletedTask, _ => Task.CompletedTask, () => { onCompleted(); return Task.CompletedTask; }));
+        }
+
+        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return Do(observer, x => { onNext(x); return Task.CompletedTask; }, ex => { onError(ex); return Task.CompletedTask; }, () => { onCompleted(); return Task.CompletedTask; });
+        }
+    }
+}

+ 130 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/DoWhile.cs

@@ -0,0 +1,130 @@
+// 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.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        // REVIEW: Use a tail-recursive sink.
+
+        public static IAsyncObservable<TSource> DoWhile<TSource>(IAsyncObservable<TSource> source, Func<bool> condition)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+
+            return Create<TSource>(async observer =>
+            {
+                var subscription = new SerialAsyncDisposable();
+
+                var o = default(IAsyncObserver<TSource>);
+
+                o = AsyncObserver.CreateUnsafe<TSource>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        MoveNext
+                    );
+
+                async Task Subscribe()
+                {
+                    var sad = new SingleAssignmentAsyncDisposable();
+                    await subscription.AssignAsync(sad).ConfigureAwait(false);
+
+                    var d = await source.SubscribeSafeAsync(o).ConfigureAwait(false);
+                    await sad.AssignAsync(d).ConfigureAwait(false);
+                }
+
+                async Task MoveNext()
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = condition();
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        await Subscribe().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+
+                await Subscribe().ConfigureAwait(false);
+
+                return subscription;
+            });
+        }
+
+        public static IAsyncObservable<TSource> DoWhile<TSource>(IAsyncObservable<TSource> source, Func<Task<bool>> condition)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+
+            return Create<TSource>(async observer =>
+            {
+                var subscription = new SerialAsyncDisposable();
+
+                var o = default(IAsyncObserver<TSource>);
+
+                o = AsyncObserver.CreateUnsafe<TSource>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        MoveNext
+                    );
+
+                async Task Subscribe()
+                {
+                    var sad = new SingleAssignmentAsyncDisposable();
+                    await subscription.AssignAsync(sad).ConfigureAwait(false);
+
+                    var d = await source.SubscribeSafeAsync(o).ConfigureAwait(false);
+                    await sad.AssignAsync(d).ConfigureAwait(false);
+                }
+
+                async Task MoveNext()
+                {
+                    var b = default(bool);
+
+                    try
+                    {
+                        b = await condition().ConfigureAwait(false);
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        await Subscribe().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+
+                await Subscribe().ConfigureAwait(false);
+
+                return subscription;
+            });
+        }
+    }
+}

+ 48 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ElementAt.cs

@@ -0,0 +1,48 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> ElementAt<TSource>(this IAsyncObservable<TSource> source, int index)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.ElementAt(observer, index)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> ElementAt<TSource>(IAsyncObserver<TSource> observer, int index)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    if (index-- == 0)
+                    {
+                        await observer.OnNextAsync(x).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnErrorAsync(new ArgumentOutOfRangeException("The element at the specified index was not found.")).ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 47 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ElementAtOrDefault.cs

@@ -0,0 +1,47 @@
+// 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. 
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> ElementAtOrDefault<TSource>(this IAsyncObservable<TSource> source, int index)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.ElementAtOrDefault(observer, index)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> ElementAtOrDefault<TSource>(IAsyncObserver<TSource> observer, int index)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    if (index-- == 0)
+                    {
+                        await observer.OnNextAsync(x).ConfigureAwait(false);
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(default(TSource)).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+    }
+}

+ 46 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Empty.cs

@@ -0,0 +1,46 @@
+// 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.Reactive.Concurrency;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Empty<TSource>()
+        {
+            return Create<TSource>(observer => AsyncObserver.Empty(observer));
+        }
+
+        public static IAsyncObservable<TSource> Empty<TSource>(IAsyncScheduler scheduler)
+        {
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Create<TSource>(observer => AsyncObserver.Empty(observer, scheduler));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static Task<IAsyncDisposable> Empty<TSource>(IAsyncObserver<TSource> observer) => Empty(observer, ImmediateAsyncScheduler.Instance);
+
+        public static Task<IAsyncDisposable> Empty<TSource>(IAsyncObserver<TSource> observer, IAsyncScheduler scheduler)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return scheduler.ScheduleAsync(async ct =>
+            {
+                if (!ct.IsCancellationRequested)
+                {
+                    await observer.OnCompletedAsync().RendezVous(scheduler, ct);
+                }
+            });
+        }
+    }
+}

+ 62 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/Finally.cs

@@ -0,0 +1,62 @@
+// 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.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> Finally<TSource>(this IAsyncObservable<TSource> source, Action finallyAction)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (finallyAction == null)
+                throw new ArgumentNullException(nameof(finallyAction));
+
+            return Create<TSource>(async observer =>
+            {
+                var subscription = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+
+                return AsyncDisposable.Create(async () =>
+                {
+                    try
+                    {
+                        await subscription.DisposeAsync().ConfigureAwait(false);
+                    }
+                    finally
+                    {
+                        finallyAction();
+                    }
+                });
+            });
+        }
+
+        public static IAsyncObservable<TSource> Finally<TSource>(this IAsyncObservable<TSource> source, Func<Task> finallyAction)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (finallyAction == null)
+                throw new ArgumentNullException(nameof(finallyAction));
+
+            return Create<TSource>(async observer =>
+            {
+                var subscription = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
+
+                return AsyncDisposable.Create(async () =>
+                {
+                    try
+                    {
+                        await subscription.DisposeAsync().ConfigureAwait(false);
+                    }
+                    finally
+                    {
+                        await finallyAction().ConfigureAwait(false);
+                    }
+                });
+            });
+        }
+    }
+}

+ 85 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/First.cs

@@ -0,0 +1,85 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> FirstAsync<TSource>(this IAsyncObservable<TSource> source) => First(source);
+        public static IAsyncObservable<TSource> FirstAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate) => First(source, predicate);
+        public static IAsyncObservable<TSource> FirstAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate) => First(source, predicate);
+
+        public static IAsyncObservable<TSource> First<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.First(observer)));
+        }
+
+        public static IAsyncObservable<TSource> First<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.First(observer, predicate)));
+        }
+
+        public static IAsyncObservable<TSource> First<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.First(observer, predicate)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> First<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> First<TSource>(IAsyncObserver<TSource> observer, Func<TSource, bool> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(First(observer), predicate);
+        }
+
+        public static IAsyncObserver<TSource> First<TSource>(IAsyncObserver<TSource> observer, Func<TSource, Task<bool>> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(First(observer), predicate);
+        }
+    }
+}

+ 86 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FirstOrDefault.cs

@@ -0,0 +1,86 @@
+// 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.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TSource> FirstOrDefaultAsync<TSource>(this IAsyncObservable<TSource> source) => FirstOrDefault(source);
+        public static IAsyncObservable<TSource> FirstOrDefaultAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate) => FirstOrDefault(source, predicate);
+        public static IAsyncObservable<TSource> FirstOrDefaultAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate) => FirstOrDefault(source, predicate);
+
+        public static IAsyncObservable<TSource> FirstOrDefault<TSource>(this IAsyncObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.FirstOrDefault(observer)));
+        }
+
+        public static IAsyncObservable<TSource> FirstOrDefault<TSource>(this IAsyncObservable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.FirstOrDefault(observer, predicate)));
+        }
+
+        public static IAsyncObservable<TSource> FirstOrDefault<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task<bool>> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create<TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.FirstOrDefault(observer, predicate)));
+        }
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncObserver<TSource> FirstOrDefault<TSource>(IAsyncObserver<TSource> observer)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return Create<TSource>(
+                async x =>
+                {
+                    await observer.OnNextAsync(x).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                },
+                observer.OnErrorAsync,
+                async () =>
+                {
+                    await observer.OnNextAsync(default(TSource)).ConfigureAwait(false);
+                    await observer.OnCompletedAsync().ConfigureAwait(false);
+                }
+            );
+        }
+
+        public static IAsyncObserver<TSource> FirstOrDefault<TSource>(IAsyncObserver<TSource> observer, Func<TSource, bool> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(FirstOrDefault(observer), predicate);
+        }
+
+        public static IAsyncObserver<TSource> FirstOrDefault<TSource>(IAsyncObserver<TSource> observer, Func<TSource, Task<bool>> predicate)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Where(FirstOrDefault(observer), predicate);
+        }
+    }
+}

+ 93 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/For.cs

@@ -0,0 +1,93 @@
+// 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.Generic;
+using System.Reactive.Disposables;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        // REVIEW: Use a tail-recursive sink.
+        // TODO: Add IAsyncEnumerable<T> based overlaod.
+
+        public static IAsyncObservable<TResult> For<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IAsyncObservable<TResult>> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return For(source, x => Task.FromResult(resultSelector(x)));
+        }
+
+        public static IAsyncObservable<TResult> For<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, Task<IAsyncObservable<TResult>>> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return Create<TResult>(async observer =>
+            {
+                var subscription = new SerialAsyncDisposable();
+
+                var enumerator = source.GetEnumerator();
+
+                var o = default(IAsyncObserver<TResult>);
+
+                o = AsyncObserver.CreateUnsafe<TResult>(
+                        observer.OnNextAsync,
+                        observer.OnErrorAsync,
+                        MoveNext
+                    );
+
+                async Task MoveNext()
+                {
+                    var b = default(bool);
+                    var next = default(IAsyncObservable<TResult>);
+
+                    try
+                    {
+                        b = enumerator.MoveNext();
+
+                        if (b)
+                        {
+                            next = await resultSelector(enumerator.Current).ConfigureAwait(false);
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                        return;
+                    }
+
+                    if (b)
+                    {
+                        var sad = new SingleAssignmentAsyncDisposable();
+                        await subscription.AssignAsync(sad).ConfigureAwait(false);
+
+                        var d = await next.SubscribeSafeAsync(o).ConfigureAwait(false);
+                        await sad.AssignAsync(d).ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        await observer.OnCompletedAsync().ConfigureAwait(false);
+                    }
+                }
+
+                await MoveNext().ConfigureAwait(false);
+
+                var disposeEnumerator = AsyncDisposable.Create(() =>
+                {
+                    enumerator.Dispose();
+                    return Task.CompletedTask;
+                });
+
+                return StableCompositeAsyncDisposable.Create(disposeEnumerator, subscription);
+            });
+        }
+    }
+}

+ 132 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/ForEachAsync.cs

@@ -0,0 +1,132 @@
+// 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.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext, CancellationToken token = default(CancellationToken))
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return ForEachAsyncCore(source, (x, i) => { onNext(x); return Task.CompletedTask; }, token);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task> onNext, CancellationToken token = default(CancellationToken))
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return ForEachAsyncCore(source, (x, i) => onNext(x), token);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource, int> onNext, CancellationToken token = default(CancellationToken))
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return ForEachAsyncCore(source, (x, i) => { onNext(x, i); return Task.CompletedTask; }, token);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, int, Task> onNext, CancellationToken token = default(CancellationToken))
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return ForEachAsyncCore(source, onNext, token);
+        }
+
+        private static async Task ForEachAsyncCore<TSource>(IAsyncObservable<TSource> source, Func<TSource, int, Task> onNext, CancellationToken token)
+        {
+            token.ThrowIfCancellationRequested();
+
+            var tcs = new TaskCompletionSource<object>();
+
+            var subscription = new SingleAssignmentAsyncDisposable();
+
+            using (token.Register(() =>
+            {
+                tcs.TrySetCanceled(token);
+
+                subscription.DisposeAsync().ContinueWith(t =>
+                {
+                    if (t.Exception != null)
+                    {
+                        // TODO: Trace?
+                    }
+                });
+            }))
+            {
+                var i = 0;
+
+                var o = AsyncObserver.Create<TSource>(
+                    async x =>
+                    {
+                        try
+                        {
+                            await onNext(x, checked(i++)).ConfigureAwait(false);
+                        }
+                        catch (Exception ex)
+                        {
+                            try
+                            {
+                                tcs.TrySetException(ex);
+                            }
+                            finally
+                            {
+                                await subscription.DisposeAsync().ConfigureAwait(false);
+                            }
+                        }
+                    },
+                    async ex =>
+                    {
+                        try
+                        {
+                            tcs.TrySetException(ex);
+                        }
+                        finally
+                        {
+                            await subscription.DisposeAsync().ConfigureAwait(false);
+                        }
+                    },
+                    async () =>
+                    {
+                        try
+                        {
+                            tcs.TrySetResult(null);
+                        }
+                        finally
+                        {
+                            await subscription.DisposeAsync().ConfigureAwait(false);
+                        }
+                    }
+                );
+
+                //
+                // NB: If any of the lines below throw, the result will go into the Task returned from the async method.
+                //     There's also no need to use SubscribeSafeAsync here; the exception will propagate just fine.
+                //
+
+                var d = await source.SubscribeAsync(o).ConfigureAwait(false);
+
+                await subscription.AssignAsync(d).ConfigureAwait(false);
+            }
+
+            await tcs.Task.ConfigureAwait(false);
+        }
+    }
+}

+ 85 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsync.cs

@@ -0,0 +1,85 @@
+// 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.Reactive.Concurrency;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Reactive.Linq
+{
+    partial class AsyncObservable
+    {
+        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync)
+        {
+            if (functionAsync == null)
+                throw new ArgumentNullException(nameof(functionAsync));
+
+            return Defer(() => StartAsync(functionAsync));
+        }
+
+        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, IAsyncScheduler scheduler)
+        {
+            if (functionAsync == null)
+                throw new ArgumentNullException(nameof(functionAsync));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Defer(() => StartAsync(functionAsync, scheduler));
+        }
+
+        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync)
+        {
+            if (functionAsync == null)
+                throw new ArgumentNullException(nameof(functionAsync));
+
+            return Defer(() => StartAsync(functionAsync));
+        }
+
+        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, IAsyncScheduler scheduler)
+        {
+            if (functionAsync == null)
+                throw new ArgumentNullException(nameof(functionAsync));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Defer(() => StartAsync(functionAsync, scheduler));
+        }
+
+        public static IAsyncObservable<Unit> FromAsync(Func<Task> actionAsync)
+        {
+            if (actionAsync == null)
+                throw new ArgumentNullException(nameof(actionAsync));
+
+            return Defer(() => StartAsync(actionAsync));
+        }
+
+        public static IAsyncObservable<Unit> FromAsync(Func<Task> actionAsync, IAsyncScheduler scheduler)
+        {
+            if (actionAsync == null)
+                throw new ArgumentNullException(nameof(actionAsync));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Defer(() => StartAsync(actionAsync, scheduler));
+        }
+
+        public static IAsyncObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync)
+        {
+            if (actionAsync == null)
+                throw new ArgumentNullException(nameof(actionAsync));
+
+            return Defer(() => StartAsync(actionAsync));
+        }
+
+        public static IAsyncObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, IAsyncScheduler scheduler)
+        {
+            if (actionAsync == null)
+                throw new ArgumentNullException(nameof(actionAsync));
+            if (scheduler == null)
+                throw new ArgumentNullException(nameof(scheduler));
+
+            return Defer(() => StartAsync(actionAsync, scheduler));
+        }
+    }
+}

+ 1398 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsyncPattern.Generated.cs

@@ -0,0 +1,1398 @@
+// 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.Reactive.Subjects;
+
+namespace System.Reactive.Linq
+{
+    // REVIEW: Consider if these are worth retaining in the async space.
+
+    partial class AsyncObservable
+    {
+        public static Func<IAsyncObservable<TResult>> FromAsyncPattern<TResult>(Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return () =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, IAsyncObservable<TResult>> FromAsyncPattern<T1, TResult>(Func<T1, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, TResult>(Func<T1, T2, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, TResult>(Func<T1, T2, T3, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, TResult>(Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, TResult>(Func<T1, T2, T3, T4, T5, T6, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, IAsyncObservable<TResult>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<IAsyncObservable<Unit>> FromAsyncPattern(Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return () =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, IAsyncObservable<Unit>> FromAsyncPattern<T1>(Func<T1, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2>(Func<T1, T2, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3>(Func<T1, T2, T3, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4>(Func<T1, T2, T3, T4, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6>(Func<T1, T2, T3, T4, T5, T6, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7>(Func<T1, T2, T3, T4, T5, T6, T7, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8>(Func<T1, T2, T3, T4, T5, T6, T7, T8, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+        public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+    }
+
+    partial class AsyncObserver
+    {
+        public static IAsyncResult FromAsyncPattern<TResult>(IAsyncObserver<TResult> observer, Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, TResult>(IAsyncObserver<TResult> observer, Func<T1, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(IAsyncObserver<TResult> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+        public static IAsyncResult FromAsyncPattern(IAsyncObserver<Unit> observer, Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            });
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1>(IAsyncObserver<Unit> observer, Func<T1, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2>(IAsyncObserver<Unit> observer, Func<T1, T2, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+        }
+
+        public static IAsyncResult FromAsyncPattern<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(IAsyncObserver<Unit> observer, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+        }
+
+    }
+}

+ 216 - 0
AsyncRx.NET/System.Reactive.Async.Linq/System/Reactive/Linq/Operators/FromAsyncPattern.Generated.tt

@@ -0,0 +1,216 @@
+// 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. 
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+using System.Reactive.Subjects;
+
+namespace System.Reactive.Linq
+{
+    // REVIEW: Consider if these are worth retaining in the async space.
+
+    partial class AsyncObservable
+    {
+<#
+for (var i = 0; i <= 14; i++)
+{
+    var args = Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "IAsyncObservable<TResult>" });
+    var ret = "Func<" + string.Join(", ", args) + ">";
+
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "TResult" }));
+    var pars = string.Join(", ", Enumerable.Range(1, i).Select(j => "arg" + j));
+
+    var begin = "Func<" + string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "AsyncCallback, object, IAsyncResult" })) + ">";
+    var end = "Func<IAsyncResult, TResult>";
+
+    var invokeArgs = pars;
+
+    if (i > 0)
+    {
+        invokeArgs = ", " + invokeArgs;
+    }
+#>
+        public static <#=ret#> FromAsyncPattern<<#=genArgs#>>(<#=begin#> begin, <#=end#> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (<#=pars#>) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<TResult>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end<#=invokeArgs#>);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<TResult>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+<#
+}
+#>
+<#
+for (var i = 0; i <= 14; i++)
+{
+    var args = Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "IAsyncObservable<Unit>" });
+    var ret = "Func<" + string.Join(", ", args) + ">";
+
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
+    var pars = string.Join(", ", Enumerable.Range(1, i).Select(j => "arg" + j));
+
+    var begin = "Func<" + string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "AsyncCallback, object, IAsyncResult" })) + ">";
+    var end = "Func<IAsyncResult, Unit>";
+
+    if (genArgs != "")
+    {
+        genArgs = "<" + genArgs + ">";
+    }
+
+    var invokeArgs = pars;
+
+    if (i > 0)
+    {
+        invokeArgs = ", " + invokeArgs;
+    }
+#>
+        public static <#=ret#> FromAsyncPattern<#=genArgs#>(<#=begin#> begin, <#=end#> end)
+        {
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return (<#=pars#>) =>
+            {
+                var subject = new SequentialAsyncAsyncSubject<Unit>();
+
+                try
+                {
+                    AsyncObserver.FromAsyncPattern(subject, begin, end<#=invokeArgs#>);
+                }
+                catch (Exception ex)
+                {
+                    return Throw<Unit>(ex);
+                }
+
+                return subject.AsAsyncObservable();
+            };
+        }
+
+<#
+}
+#>
+    }
+
+    partial class AsyncObserver
+    {
+<#
+for (var i = 0; i <= 14; i++)
+{
+    var args = Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "IAsyncObservable<TResult>" });
+    var ret = "Func<" + string.Join(", ", args) + ">";
+
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "TResult" }));
+    var pars = string.Join(", ", Enumerable.Range(1, i).Select(j => "arg" + j));
+
+    var begin = "Func<" + string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "AsyncCallback, object, IAsyncResult" })) + ">";
+    var end = "Func<IAsyncResult, TResult>";
+
+    var invokePars = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j + " arg" + j));
+
+    if (i > 0)
+    {
+        invokePars = ", " + invokePars;
+    }
+#>
+        public static IAsyncResult FromAsyncPattern<<#=genArgs#>>(IAsyncObserver<TResult> observer, <#=begin#> begin, <#=end#> end<#=invokePars#>)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return begin(<#=pars + (i > 0 ? ", " : "")#>async iar =>
+            {
+                TResult result;
+
+                try
+                {
+                    result = end(iar);
+                }
+                catch (Exception ex)
+                {
+                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
+                    return;
+                }
+
+                await observer.OnNextAsync(result).ConfigureAwait(false);
+                await observer.OnCompletedAsync().ConfigureAwait(false);
+            }, null);
+        }
+
+<#
+}
+#>
+<#
+for (var i = 0; i <= 14; i++)
+{
+    var args = Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "IAsyncObservable<Unit>" });
+    var ret = "Func<" + string.Join(", ", args) + ">";
+
+    var genArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j));
+    var pars = string.Join(", ", Enumerable.Range(1, i).Select(j => "arg" + j));
+
+    var begin = "Func<" + string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j).Concat(new[] { "AsyncCallback, object, IAsyncResult" })) + ">";
+    var end = "Func<IAsyncResult, Unit>";
+
+    if (genArgs != "")
+    {
+        genArgs = "<" + genArgs + ">";
+    }
+
+    var invokePars = string.Join(", ", Enumerable.Range(1, i).Select(j => "T" + j + " arg" + j));
+    var invokeArgs = pars;
+
+    if (i > 0)
+    {
+        invokePars = ", " + invokePars;
+        invokeArgs = ", " + invokeArgs;
+    }
+#>
+        public static IAsyncResult FromAsyncPattern<#=genArgs#>(IAsyncObserver<Unit> observer, <#=begin#> begin, <#=end#> end<#=invokePars#>)
+        {
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+            if (begin == null)
+                throw new ArgumentNullException(nameof(begin));
+            if (end == null)
+                throw new ArgumentNullException(nameof(end));
+
+            return FromAsyncPattern(observer, begin, iar =>
+            {
+                end(iar);
+                return Unit.Default;
+            }<#=invokeArgs#>);
+        }
+
+<#
+}
+#>
+    }
+}

Some files were not shown because too many files changed in this diff