Skip to content

Commit 8636d56

Browse files
committed
Merge pull request #116 from PowerShell/daviwil/remove-asyncex
Remove Nito.AsyncEx dependency, add replacements
2 parents e435301 + 0fe1a84 commit 8636d56

28 files changed

+665
-168
lines changed

src/PowerShellEditorServices.Host.x86/PowerShellEditorServices.Host.x86.csproj

-13
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,6 @@
3737
</PropertyGroup>
3838
<ItemGroup>
3939
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" />
40-
<Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
41-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
42-
<Private>True</Private>
43-
</Reference>
44-
<Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
45-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
46-
<Private>True</Private>
47-
</Reference>
48-
<Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
49-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
50-
<Private>True</Private>
51-
</Reference>
5240
<Reference Include="System" />
5341
<Reference Include="System.Core" />
5442
<Reference Include="System.Xml.Linq" />
@@ -71,7 +59,6 @@
7159
<None Include="..\PowerShellEditorServices.Host\App.config">
7260
<Link>App.config</Link>
7361
</None>
74-
<None Include="packages.config" />
7562
</ItemGroup>
7663
<ItemGroup>
7764
<ProjectReference Include="..\..\submodules\PSScriptAnalyzer\Engine\ScriptAnalyzerEngine.csproj">

src/PowerShellEditorServices.Host.x86/packages.config

-4
This file was deleted.

src/PowerShellEditorServices.Host/PowerShellEditorServices.Host.csproj

-13
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,6 @@
3939
</PropertyGroup>
4040
<ItemGroup>
4141
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed" />
42-
<Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
43-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
44-
<Private>True</Private>
45-
</Reference>
46-
<Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
47-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
48-
<Private>True</Private>
49-
</Reference>
50-
<Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
51-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
52-
<Private>True</Private>
53-
</Reference>
5442
<Reference Include="System" />
5543
<Reference Include="System.Core" />
5644
<Reference Include="System.Xml.Linq" />
@@ -69,7 +57,6 @@
6957
<Content Include="Microsoft.PowerShell.EditorServices.Host.DebugAdapter.cmd">
7058
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
7159
</Content>
72-
<None Include="packages.config" />
7360
</ItemGroup>
7461
<ItemGroup>
7562
<ProjectReference Include="..\..\submodules\PSScriptAnalyzer\Engine\ScriptAnalyzerEngine.csproj">

src/PowerShellEditorServices.Host/packages.config

-4
This file was deleted.

src/PowerShellEditorServices.Protocol/DebugAdapter/NextRequest.cs

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
//
55

66
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
7-
using Nito.AsyncEx;
8-
using System.Threading.Tasks;
97

108
namespace Microsoft.PowerShell.EditorServices.Protocol.DebugAdapter
119
{

src/PowerShellEditorServices.Protocol/DebugAdapter/SetExceptionBreakpointsRequest.cs

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
//
55

66
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol;
7-
using Nito.AsyncEx;
8-
using System.Threading.Tasks;
97

108
namespace Microsoft.PowerShell.EditorServices.Protocol.DebugAdapter
119
{

src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs

+13-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
//
55

66
using Microsoft.PowerShell.EditorServices.Utility;
7-
using Nito.AsyncEx;
87
using System;
98
using System.Collections.Generic;
109
using System.Threading;
@@ -26,6 +25,9 @@ public class MessageDispatcher
2625

2726
private Action<Message> responseHandler;
2827

28+
private CancellationTokenSource messageLoopCancellationToken =
29+
new CancellationTokenSource();
30+
2931
#endregion
3032

3133
#region Properties
@@ -65,22 +67,24 @@ public MessageDispatcher(
6567

6668
public void Start()
6769
{
70+
6871
// Start the main message loop thread. The Task is
6972
// not explicitly awaited because it is running on
7073
// an independent background thread.
71-
this.messageLoopThread = new AsyncContextThread(true);
74+
this.messageLoopThread = new AsyncContextThread("Message Dispatcher");
7275
this.messageLoopThread
73-
.Factory
74-
.Run(this.ListenForMessages)
76+
.Run(() => this.ListenForMessages(this.messageLoopCancellationToken.Token))
7577
.ContinueWith(this.OnListenTaskCompleted);
7678
}
7779

7880
public void Stop()
7981
{
80-
// By disposing the thread we cancel all existing work
81-
// and cause the thread to be destroyed.
82+
// Stop the message loop thread
8283
if (this.messageLoopThread != null)
83-
this.messageLoopThread.Dispose();
84+
{
85+
this.messageLoopCancellationToken.Cancel();
86+
this.messageLoopThread.Stop();
87+
}
8488
}
8589

8690
public void SetRequestHandler<TParams, TResult>(
@@ -181,13 +185,13 @@ protected void OnUnhandledException(Exception unhandledException)
181185

182186
#region Private Methods
183187

184-
private async Task ListenForMessages()
188+
private async Task ListenForMessages(CancellationToken cancellationToken)
185189
{
186190
this.SynchronizationContext = SynchronizationContext.Current;
187191

188192
// Run the message loop
189193
bool isRunning = true;
190-
while (isRunning)
194+
while (isRunning && !cancellationToken.IsCancellationRequested)
191195
{
192196
Message newMessage = null;
193197

src/PowerShellEditorServices.Protocol/MessageProtocol/MessageWriter.cs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Microsoft.PowerShell.EditorServices.Utility;
77
using Newtonsoft.Json;
88
using Newtonsoft.Json.Linq;
9-
using Nito.AsyncEx;
109
using System.IO;
1110
using System.Text;
1211
using System.Threading.Tasks;

src/PowerShellEditorServices.Protocol/PowerShellEditorServices.Protocol.csproj

-12
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@
3838
<HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
3939
<Private>True</Private>
4040
</Reference>
41-
<Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
42-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
43-
<Private>True</Private>
44-
</Reference>
45-
<Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
46-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
47-
<Private>True</Private>
48-
</Reference>
49-
<Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
50-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
51-
<Private>True</Private>
52-
</Reference>
5341
<Reference Include="System" />
5442
<Reference Include="System.Core" />
5543
<Reference Include="System.Xml.Linq" />

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
99
using Microsoft.PowerShell.EditorServices.Protocol.Messages;
1010
using Microsoft.PowerShell.EditorServices.Utility;
11-
using Nito.AsyncEx;
1211
using System;
1312
using System.Collections.Generic;
1413
using System.IO;
@@ -780,7 +779,7 @@ private Task RunScriptDiagnostics(
780779
if (!this.currentSettings.ScriptAnalysis.Enable.Value)
781780
{
782781
// If the user has disabled script analysis, skip it entirely
783-
return TaskConstants.Completed;
782+
return Task.FromResult(true);
784783
}
785784

786785
// If there's an existing task, attempt to cancel it
@@ -806,7 +805,9 @@ private Task RunScriptDiagnostics(
806805
"Exception while cancelling analysis task:\n\n{0}",
807806
e.ToString()));
808807

809-
return TaskConstants.Canceled;
808+
TaskCompletionSource<bool> cancelTask = new TaskCompletionSource<bool>();
809+
cancelTask.SetCanceled();
810+
return cancelTask.Task;
810811
}
811812

812813
// Create a fresh cancellation token and then start the task.
@@ -826,7 +827,7 @@ private Task RunScriptDiagnostics(
826827
TaskCreationOptions.None,
827828
TaskScheduler.Default);
828829

829-
return TaskConstants.Completed;
830+
return Task.FromResult(true);
830831
}
831832

832833
private static async Task DelayThenInvokeDiagnostics(
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
4-
<package id="Nito.AsyncEx" version="3.0.1" targetFramework="net45" />
54
</packages>

src/PowerShellEditorServices/PowerShellEditorServices.csproj

+5-15
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@
3838
<DocumentationFile>bin\Release\Microsoft.PowerShell.EditorServices.XML</DocumentationFile>
3939
</PropertyGroup>
4040
<ItemGroup>
41-
<Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
42-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
43-
<Private>True</Private>
44-
</Reference>
45-
<Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
46-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
47-
<Private>True</Private>
48-
</Reference>
49-
<Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
50-
<HintPath>..\..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
51-
<Private>True</Private>
52-
</Reference>
5341
<Reference Include="System" />
5442
<Reference Include="System.Core" />
5543
<Reference Include="System.Management.Automation" />
@@ -109,7 +97,12 @@
10997
<Compile Include="Session\SessionPSHostRawUserInterface.cs" />
11098
<Compile Include="Session\SessionPSHostUserInterface.cs" />
11199
<Compile Include="Session\SessionStateChangedEventArgs.cs" />
100+
<Compile Include="Utility\AsyncContextThread.cs" />
101+
<Compile Include="Utility\AsyncLock.cs" />
102+
<Compile Include="Utility\AsyncQueue.cs" />
103+
<Compile Include="Utility\AsyncContext.cs" />
112104
<Compile Include="Utility\Logger.cs" />
105+
<Compile Include="Utility\ThreadSynchronizationContext.cs" />
113106
<Compile Include="Utility\Validate.cs" />
114107
<Compile Include="Workspace\BufferRange.cs" />
115108
<Compile Include="Workspace\FileChange.cs" />
@@ -119,9 +112,6 @@
119112
<Compile Include="Workspace\ScriptRegion.cs" />
120113
<Compile Include="Workspace\Workspace.cs" />
121114
</ItemGroup>
122-
<ItemGroup>
123-
<None Include="packages.config" />
124-
</ItemGroup>
125115
<ItemGroup>
126116
<ProjectReference Include="..\..\submodules\PSScriptAnalyzer\Engine\ScriptAnalyzerEngine.csproj">
127117
<Project>{f4bde3d0-3eef-4157-8a3e-722df7adef60}</Project>

src/PowerShellEditorServices/Session/PowerShellContext.cs

+27-39
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
using Microsoft.PowerShell.EditorServices.Console;
77
using Microsoft.PowerShell.EditorServices.Utility;
8-
using Nito.AsyncEx;
98
using System;
109
using System.Collections;
1110
using System.Globalization;
@@ -44,8 +43,7 @@ public class PowerShellContext : IDisposable
4443
private TaskCompletionSource<IPipelineExecutionRequest> pipelineResultTask;
4544

4645
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>();
4947

5048
#endregion
5149

@@ -115,6 +113,7 @@ public PowerShellContext()
115113
this.ownsInitialRunspace = true;
116114

117115
this.Initialize(runspace);
116+
118117
}
119118

120119
/// <summary>
@@ -164,6 +163,10 @@ private void Initialize(Runspace initialRunspace)
164163
#endif
165164

166165
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();
167170
}
168171

169172
private Version GetPowerShellVersion()
@@ -198,21 +201,19 @@ private Version GetPowerShellVersion()
198201
/// <returns>A RunspaceHandle instance that gives access to the session's runspace.</returns>
199202
public Task<RunspaceHandle> GetRunspaceHandle()
200203
{
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);
216217
}
217218

218219
/// <summary>
@@ -532,30 +533,17 @@ internal void ReleaseRunspaceHandle(RunspaceHandle runspaceHandle)
532533
{
533534
Validate.IsNotNull("runspaceHandle", runspaceHandle);
534535

535-
IDisposable dequeuedTask = null;
536-
537-
lock (this.runspaceMutex)
536+
if (this.runspaceWaitQueue.IsEmpty)
538537
{
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();
553540
}
554-
555-
// If a queued task was dequeued, call Dispose to cause it to be executed.
556-
if (dequeuedTask != null)
541+
else
557542
{
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");
559547
}
560548
}
561549

0 commit comments

Comments
 (0)