1
1
using System ;
2
2
using System . Collections . Concurrent ;
3
3
using System . Collections . Generic ;
4
+ using System . Diagnostics ;
4
5
using System . Diagnostics . Contracts ;
5
6
using System . Management . Automation ;
6
7
using System . Management . Automation . Runspaces ;
7
8
using System . Threading ;
8
9
9
10
namespace PSParallel
10
11
{
11
- class PowershellPool : IDisposable
12
+ sealed class PowershellPool : IDisposable
12
13
{
13
14
private int m_busyCount ;
14
15
private int m_processedCount ;
15
16
private readonly CancellationToken m_cancellationToken ;
16
17
private readonly RunspacePool m_runspacePool ;
17
18
private readonly List < PowerShellPoolMember > m_poolMembers ;
18
- private readonly BlockingCollection < PowerShellPoolMember > m_availablePoolMembers = new BlockingCollection < PowerShellPoolMember > ( new ConcurrentStack < PowerShellPoolMember > ( ) ) ;
19
+ private readonly BlockingCollection < PowerShellPoolMember > m_availablePoolMembers = new BlockingCollection < PowerShellPoolMember > ( new ConcurrentQueue < PowerShellPoolMember > ( ) ) ;
19
20
public readonly PowerShellPoolStreams Streams = new PowerShellPoolStreams ( ) ;
20
21
21
22
public int ProcessedCount => m_processedCount ;
@@ -26,9 +27,9 @@ public PowershellPool(int poolSize, InitialSessionState initialSessionState, Can
26
27
m_processedCount = 0 ;
27
28
m_cancellationToken = cancellationToken ;
28
29
29
- for ( int i = 0 ; i < poolSize ; i ++ )
30
+ for ( var i = 0 ; i < poolSize ; i ++ )
30
31
{
31
- var powerShellPoolMember = new PowerShellPoolMember ( this ) ;
32
+ var powerShellPoolMember = new PowerShellPoolMember ( this , i + 1 ) ;
32
33
m_poolMembers . Add ( powerShellPoolMember ) ;
33
34
m_availablePoolMembers . Add ( powerShellPoolMember ) ;
34
35
}
@@ -37,16 +38,17 @@ public PowershellPool(int poolSize, InitialSessionState initialSessionState, Can
37
38
m_runspacePool . SetMaxRunspaces ( poolSize ) ;
38
39
}
39
40
40
- public void AddInput ( ScriptBlock scriptblock , PSObject inputObject )
41
- {
42
- try {
43
- var powerShell = WaitForAvailablePowershell ( ) ;
44
- Interlocked . Increment ( ref m_busyCount ) ;
45
- powerShell . BeginInvoke ( scriptblock , inputObject ) ;
46
- }
47
- catch ( OperationCanceledException )
41
+ public bool TryAddInput ( ScriptBlock scriptblock , PSObject inputObject )
42
+ {
43
+ PowerShellPoolMember poolMember ;
44
+ if ( ! TryWaitForAvailablePowershell ( 100 , out poolMember ) )
48
45
{
46
+ return false ;
49
47
}
48
+
49
+ Interlocked . Increment ( ref m_busyCount ) ;
50
+ poolMember . BeginInvoke ( scriptblock , inputObject ) ;
51
+ return true ;
50
52
}
51
53
52
54
public void Open ( )
@@ -76,11 +78,19 @@ public bool WaitForAllPowershellCompleted(int timeoutMilliseconds)
76
78
return false ;
77
79
}
78
80
79
- private PowerShellPoolMember WaitForAvailablePowershell ( )
80
- {
81
- var poolmember = m_availablePoolMembers . Take ( m_cancellationToken ) ;
82
- poolmember . PowerShell . RunspacePool = m_runspacePool ;
83
- return poolmember ;
81
+ private bool TryWaitForAvailablePowershell ( int milliseconds , out PowerShellPoolMember poolMember )
82
+ {
83
+ if ( ! m_availablePoolMembers . TryTake ( out poolMember , milliseconds , m_cancellationToken ) )
84
+ {
85
+ m_cancellationToken . ThrowIfCancellationRequested ( ) ;
86
+ Debug . WriteLine ( $ "WaitForAvailablePowershell - TryTake failed") ;
87
+ poolMember = null ;
88
+ return false ;
89
+ }
90
+
91
+ poolMember . PowerShell . RunspacePool = m_runspacePool ;
92
+ Debug . WriteLine ( $ "WaitForAvailablePowershell - Busy: { m_busyCount } _processed { m_processedCount } , member = { poolMember . Index } ") ;
93
+ return true ;
84
94
}
85
95
86
96
@@ -95,10 +105,13 @@ public void ReportAvailable(PowerShellPoolMember poolmember)
95
105
{
96
106
Interlocked . Decrement ( ref m_busyCount ) ;
97
107
Interlocked . Increment ( ref m_processedCount ) ;
98
- if ( ! m_cancellationToken . IsCancellationRequested )
99
- {
100
- m_availablePoolMembers . Add ( poolmember ) ;
101
- }
108
+ while ( ! m_availablePoolMembers . TryAdd ( poolmember , 1000 , m_cancellationToken ) )
109
+ {
110
+ m_cancellationToken . ThrowIfCancellationRequested ( ) ;
111
+ Debug . WriteLine ( $ "WaitForAvailablePowershell - TryAdd failed") ;
112
+ }
113
+ Debug . WriteLine ( $ "ReportAvailable - Busy: { m_busyCount } _processed { m_processedCount } , member = { poolmember . Index } ") ;
114
+
102
115
}
103
116
104
117
public void ReportStopped ( PowerShellPoolMember powerShellPoolMember )
0 commit comments