@@ -40,25 +40,27 @@ public void StopWork()
40
40
class WorkPool
41
41
{
42
42
readonly ConcurrentQueue < Action > _actions ;
43
- readonly SemaphoreSlim _semaphore = new SemaphoreSlim ( 0 ) ;
44
43
readonly CancellationTokenSource _tokenSource ;
44
+ CancellationTokenRegistration _tokenRegistration ;
45
+ volatile TaskCompletionSource < bool > _syncSource = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
45
46
private Task _worker ;
46
47
47
48
public WorkPool ( )
48
49
{
49
50
_actions = new ConcurrentQueue < Action > ( ) ;
50
51
_tokenSource = new CancellationTokenSource ( ) ;
52
+ _tokenRegistration = _tokenSource . Token . Register ( ( ) => _syncSource . TrySetCanceled ( ) ) ;
51
53
}
52
54
53
55
public void Start ( )
54
56
{
55
- _worker = Task . Run ( Loop ) ;
57
+ _worker = Task . Run ( Loop , CancellationToken . None ) ;
56
58
}
57
59
58
60
public void Enqueue ( Action action )
59
61
{
60
62
_actions . Enqueue ( action ) ;
61
- _semaphore . Release ( ) ;
63
+ _syncSource . TrySetResult ( true ) ;
62
64
}
63
65
64
66
async Task Loop ( )
@@ -67,21 +69,23 @@ async Task Loop()
67
69
{
68
70
try
69
71
{
70
- await _semaphore . WaitAsync ( _tokenSource . Token ) . ConfigureAwait ( false ) ;
72
+ await _syncSource . Task . ConfigureAwait ( false ) ;
73
+ _syncSource = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
71
74
}
72
75
catch ( TaskCanceledException )
73
76
{
74
77
// Swallowing the task cancellation exception for the semaphore in case we are stopping.
75
78
}
76
79
77
- if ( ! _tokenSource . IsCancellationRequested && _actions . TryDequeue ( out Action action ) )
80
+ while ( _tokenSource . IsCancellationRequested && _actions . TryDequeue ( out Action action ) )
78
81
{
79
82
try
80
83
{
81
84
action ( ) ;
82
85
}
83
86
catch ( Exception )
84
87
{
88
+ // ignored
85
89
}
86
90
}
87
91
@@ -91,6 +95,7 @@ async Task Loop()
91
95
public void Stop ( )
92
96
{
93
97
_tokenSource . Cancel ( ) ;
98
+ _tokenRegistration . Dispose ( ) ;
94
99
}
95
100
}
96
101
}
0 commit comments