@@ -11,13 +11,19 @@ public async Task RunAsync_And_RunManyAsync_SameKey_OnlyOneLoaderRuns()
1111 {
1212 var protector = new InMemorySingleFlightProtector ( ) ;
1313 int loaderCallCount = 0 ;
14- async Task < int > LoaderSingle ( ) {
14+
15+ var startGate = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
16+
17+ async Task < int > LoaderSingle ( )
18+ {
19+ await startGate . Task ;
1520 loaderCallCount ++ ;
1621 await Task . Delay ( 30 ) ;
1722 return 42 ;
1823 }
1924 async Task < IDictionary < string , int > > LoaderBatch ( IEnumerable < string > keys )
2025 {
26+ await startGate . Task ;
2127 loaderCallCount ++ ;
2228 await Task . Delay ( 30 ) ;
2329 return keys . ToDictionary ( k => k , _ => 42 ) ;
@@ -28,6 +34,8 @@ async Task<IDictionary<string, int>> LoaderBatch(IEnumerable<string> keys)
2834 var batchTasks = protector . RunManyAsync ( [ key ] , LoaderBatch ) ;
2935 var batchTask = batchTasks [ key ] ;
3036
37+ startGate . TrySetResult ( ) ;
38+
3139 var results = await Task . WhenAll ( singleTask , batchTask ) ;
3240 Assert . Multiple ( ( ) =>
3341 {
@@ -97,15 +105,19 @@ public async Task ManyParallelRunAsync_And_RunManyAsync_MixedOverlap_OnlyOneLoad
97105 var protector = new InMemorySingleFlightProtector ( ) ;
98106 var loaderCallCount = new ConcurrentDictionary < string , int > ( ) ;
99107
108+ var startGate = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
109+
100110 async Task < string > LoaderSingle ( string key )
101111 {
112+ await startGate . Task ;
102113 loaderCallCount . AddOrUpdate ( key , 1 , ( _ , v ) => v + 1 ) ;
103114 await Task . Delay ( 10 ) ;
104115 return key ;
105116 }
106117
107118 async Task < IDictionary < string , string > > LoaderBatch ( IEnumerable < string > keys )
108119 {
120+ await startGate . Task ;
109121 foreach ( var key in keys )
110122 {
111123 loaderCallCount . AddOrUpdate ( key , 1 , ( _ , v ) => v + 1 ) ;
@@ -126,6 +138,9 @@ async Task<IDictionary<string, string>> LoaderBatch(IEnumerable<string> keys)
126138 tasks . AddRange ( batch1 . Values ) ;
127139 tasks . AddRange ( batch2 . Values ) ;
128140 tasks . AddRange ( batch3 . Values ) ;
141+
142+ startGate . TrySetResult ( ) ;
143+
129144 var results = await Task . WhenAll ( tasks ) ;
130145
131146 foreach ( var key in allKeys )
@@ -144,8 +159,12 @@ public async Task RunManyAsync_MultipleBatchesWithPartialOverlap_OnlyOneLoaderPe
144159 {
145160 var protector = new InMemorySingleFlightProtector ( ) ;
146161 var loaderCallCount = new ConcurrentDictionary < string , int > ( ) ;
162+
163+ var startGate = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
164+
147165 async Task < IDictionary < string , int > > LoaderBatch ( IEnumerable < string > keys )
148166 {
167+ await startGate . Task ;
149168 foreach ( var key in keys )
150169 {
151170 loaderCallCount . AddOrUpdate ( key , 1 , ( _ , v ) => v + 1 ) ;
@@ -160,6 +179,9 @@ async Task<IDictionary<string, int>> LoaderBatch(IEnumerable<string> keys)
160179 var batch3 = protector . RunManyAsync ( [ "c" , "d" , "e" ] , LoaderBatch ) ;
161180 var batch4 = protector . RunManyAsync ( [ "e" , "f" ] , LoaderBatch ) ;
162181 var allTasks = batch1 . Values . Concat ( batch2 . Values ) . Concat ( batch3 . Values ) . Concat ( batch4 . Values ) ;
182+
183+ startGate . TrySetResult ( ) ;
184+
163185 var results = await Task . WhenAll ( allTasks ) ;
164186 foreach ( var key in new [ ] { "a" , "b" , "c" , "d" , "e" , "f" } )
165187 {
0 commit comments