1- using System . Collections . Generic ;
1+ using System ;
2+ using System . Collections . Generic ;
23using System . Linq ;
34using System . Threading . Tasks ;
45using StackInjector . Settings ;
@@ -8,14 +9,12 @@ namespace StackInjector.Core
89 internal abstract partial class AsyncStackWrapperCore < T >
910 {
1011 // call the semaphore
11- protected internal void ReleaseListAwaiter ( )
12- {
13- this . emptyListAwaiter . Release ( ) ;
14- }
12+ protected internal void ReleaseListAwaiter ( ) => this . _emptyListAwaiter . Release ( ) ;
13+
1514
16- public void Submit ( Task < T > work )
15+ internal void Submit ( Task < T > work )
1716 {
18- lock ( this . listAccessLock )
17+ lock ( this . _listAccessLock )
1918 this . tasks . AddLast ( work ) ;
2019
2120 // if the list was empty just an item ago, signal it's not anymore.
@@ -24,22 +23,33 @@ public void Submit ( Task<T> work )
2423 this . ReleaseListAwaiter ( ) ;
2524 }
2625
26+
2727 public bool AnyTaskLeft ( )
2828 {
29- lock ( this . listAccessLock )
29+ lock ( this . _listAccessLock )
3030 return this . tasks . Any ( ) ;
3131 }
3232
33+ public bool AnyTaskCompleted ( )
34+ {
35+ lock ( this . _listAccessLock )
36+ return this . tasks . Any ( t => t . IsCompleted ) ;
37+ }
38+
3339 public async IAsyncEnumerable < T > Elaborated ( )
3440 {
41+ this . EnsureExclusiveExecution ( true ) ;
42+
3543 while ( ! this . cancelPendingTasksSource . IsCancellationRequested )
3644 {
3745 // avoid deadlocks
3846 if ( this . AnyTaskLeft ( ) )
3947 {
4048 var completed = await Task . WhenAny ( this . tasks ) . ConfigureAwait ( false ) ;
4149
42- lock ( this . listAccessLock )
50+
51+
52+ lock ( this . _listAccessLock )
4353 this . tasks . Remove ( completed ) ;
4454
4555 yield return completed . Result ;
@@ -51,14 +61,25 @@ public async IAsyncEnumerable<T> Elaborated ()
5161 break ;
5262 }
5363 }
64+
65+ lock ( this . _listAccessLock )
66+ this . _exclusiveExecution = false ;
67+
68+ }
69+
70+ public async Task Elaborate ( )
71+ {
72+ await foreach ( var res in this . Elaborated ( ) )
73+ this . OnElaborated ? . Invoke ( res ) ;
5474 }
5575
76+
5677 // true if outher loop is to break
5778 private async Task < bool > OnNoTasksLeft ( )
5879 {
5980 // to not repeat code
6081 Task listAwaiter ( )
61- => this . emptyListAwaiter . WaitAsync ( ) ;
82+ => this . _emptyListAwaiter . WaitAsync ( ) ;
6283
6384
6485 switch ( this . Settings . _asyncWaitingMethod )
@@ -86,10 +107,18 @@ Task listAwaiter ()
86107 }
87108 }
88109
110+ private void EnsureExclusiveExecution ( bool set = false )
111+ {
112+ lock ( this . _listAccessLock ) // reused lock
113+ {
114+ if ( this . _exclusiveExecution )
115+ throw new InvalidOperationException ( ) ;
116+
117+ if ( set )
118+ this . _exclusiveExecution = set ;
119+ }
120+ }
89121
90- public bool AnyTaskCompleted ( )
91- =>
92- this . tasks . Any ( t => t . IsCompleted ) ;
93122
94123
95124 }
0 commit comments