|
5 | 5 |
|
6 | 6 | using Microsoft.PowerShell.EditorServices.Console;
|
7 | 7 | using Microsoft.PowerShell.EditorServices.Utility;
|
8 |
| -using Nito.AsyncEx; |
9 | 8 | using System;
|
10 | 9 | using System.Collections;
|
11 | 10 | using System.Globalization;
|
@@ -44,8 +43,7 @@ public class PowerShellContext : IDisposable
|
44 | 43 | private TaskCompletionSource<IPipelineExecutionRequest> pipelineResultTask;
|
45 | 44 |
|
46 | 45 | private object runspaceMutex = new object();
|
47 |
| - private RunspaceHandle currentRunspaceHandle; |
48 |
| - private IAsyncWaitQueue<RunspaceHandle> runspaceWaitQueue = new DefaultAsyncWaitQueue<RunspaceHandle>(); |
| 46 | + private AsyncQueue<RunspaceHandle> runspaceWaitQueue = new AsyncQueue<RunspaceHandle>(); |
49 | 47 |
|
50 | 48 | #endregion
|
51 | 49 |
|
@@ -115,6 +113,7 @@ public PowerShellContext()
|
115 | 113 | this.ownsInitialRunspace = true;
|
116 | 114 |
|
117 | 115 | this.Initialize(runspace);
|
| 116 | + |
118 | 117 | }
|
119 | 118 |
|
120 | 119 | /// <summary>
|
@@ -164,6 +163,10 @@ private void Initialize(Runspace initialRunspace)
|
164 | 163 | #endif
|
165 | 164 |
|
166 | 165 | this.SessionState = PowerShellContextState.Ready;
|
| 166 | + |
| 167 | + // Now that the runspace is ready, enqueue it for first use |
| 168 | + RunspaceHandle runspaceHandle = new RunspaceHandle(this.currentRunspace, this); |
| 169 | + this.runspaceWaitQueue.EnqueueAsync(runspaceHandle).Wait(); |
167 | 170 | }
|
168 | 171 |
|
169 | 172 | private Version GetPowerShellVersion()
|
@@ -198,21 +201,19 @@ private Version GetPowerShellVersion()
|
198 | 201 | /// <returns>A RunspaceHandle instance that gives access to the session's runspace.</returns>
|
199 | 202 | public Task<RunspaceHandle> GetRunspaceHandle()
|
200 | 203 | {
|
201 |
| - lock (this.runspaceMutex) |
202 |
| - { |
203 |
| - if (this.currentRunspaceHandle == null) |
204 |
| - { |
205 |
| - this.currentRunspaceHandle = new RunspaceHandle(this.currentRunspace, this); |
206 |
| - TaskCompletionSource<RunspaceHandle> tcs = new TaskCompletionSource<RunspaceHandle>(); |
207 |
| - tcs.SetResult(this.currentRunspaceHandle); |
208 |
| - return tcs.Task; |
209 |
| - } |
210 |
| - else |
211 |
| - { |
212 |
| - // TODO: Use CancellationToken? |
213 |
| - return this.runspaceWaitQueue.Enqueue(); |
214 |
| - } |
215 |
| - } |
| 204 | + return this.GetRunspaceHandle(CancellationToken.None); |
| 205 | + } |
| 206 | + |
| 207 | + /// <summary> |
| 208 | + /// Gets a RunspaceHandle for the session's runspace. This |
| 209 | + /// handle is used to gain temporary ownership of the runspace |
| 210 | + /// so that commands can be executed against it directly. |
| 211 | + /// </summary> |
| 212 | + /// <param name="cancellationToken">A CancellationToken that can be used to cancel the request.</param> |
| 213 | + /// <returns>A RunspaceHandle instance that gives access to the session's runspace.</returns> |
| 214 | + public Task<RunspaceHandle> GetRunspaceHandle(CancellationToken cancellationToken) |
| 215 | + { |
| 216 | + return this.runspaceWaitQueue.DequeueAsync(cancellationToken); |
216 | 217 | }
|
217 | 218 |
|
218 | 219 | /// <summary>
|
@@ -532,30 +533,17 @@ internal void ReleaseRunspaceHandle(RunspaceHandle runspaceHandle)
|
532 | 533 | {
|
533 | 534 | Validate.IsNotNull("runspaceHandle", runspaceHandle);
|
534 | 535 |
|
535 |
| - IDisposable dequeuedTask = null; |
536 |
| - |
537 |
| - lock (this.runspaceMutex) |
| 536 | + if (this.runspaceWaitQueue.IsEmpty) |
538 | 537 | {
|
539 |
| - if (runspaceHandle != this.currentRunspaceHandle) |
540 |
| - { |
541 |
| - throw new InvalidOperationException("Released runspace handle was not the current handle."); |
542 |
| - } |
543 |
| - |
544 |
| - this.currentRunspaceHandle = null; |
545 |
| - |
546 |
| - if (!this.runspaceWaitQueue.IsEmpty) |
547 |
| - { |
548 |
| - this.currentRunspaceHandle = new RunspaceHandle(this.currentRunspace, this); |
549 |
| - dequeuedTask = |
550 |
| - this.runspaceWaitQueue.Dequeue( |
551 |
| - this.currentRunspaceHandle); |
552 |
| - } |
| 538 | + var newRunspaceHandle = new RunspaceHandle(this.currentRunspace, this); |
| 539 | + this.runspaceWaitQueue.EnqueueAsync(newRunspaceHandle).Wait(); |
553 | 540 | }
|
554 |
| - |
555 |
| - // If a queued task was dequeued, call Dispose to cause it to be executed. |
556 |
| - if (dequeuedTask != null) |
| 541 | + else |
557 | 542 | {
|
558 |
| - dequeuedTask.Dispose(); |
| 543 | + // Write the situation to the log since this shouldn't happen |
| 544 | + Logger.Write( |
| 545 | + LogLevel.Error, |
| 546 | + "The PowerShellContext.runspaceWaitQueue has more than one item"); |
559 | 547 | }
|
560 | 548 | }
|
561 | 549 |
|
|
0 commit comments