Skip to content

Commit 526b4b7

Browse files
SyncTaskScheduler as a separete class.
1 parent 9176172 commit 526b4b7

File tree

9 files changed

+96
-47
lines changed

9 files changed

+96
-47
lines changed

src/ResourceManager/Common/Commands.Common.Strategies/Commands.Common.Strategies.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
<Compile Include="StateOperationContext.cs" />
7777
<Compile Include="Compute\ComputeStrategy.cs" />
7878
<Compile Include="Compute\VirtualMachineStrategy.cs" />
79+
<Compile Include="SyncTaskScheduler.cs" />
7980
<Compile Include="UpdateStateExtensions.cs" />
8081
<Compile Include="CreateOrUpdateAsyncParams.cs" />
8182
<Compile Include="EntityConfigExtensions.cs" />

src/ResourceManager/Compute/Commands.Compute/Strategies/MessageLoop.cs renamed to src/ResourceManager/Common/Commands.Common.Strategies/SyncTaskScheduler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717
using System.Threading;
1818
using System.Threading.Tasks;
1919

20-
namespace Microsoft.Azure.Commands.Compute.Strategies
20+
namespace Microsoft.Azure.Commands.Common.Strategies
2121
{
22-
internal sealed class MessageLoop
22+
public sealed class SyncTaskScheduler
2323
{
2424
readonly ConcurrentQueue<Task> _Tasks = new ConcurrentQueue<Task>();
2525

2626
public async Task<T> Invoke<T>(Func<T> func)
2727
{
2828
var task = new Task<T>(func);
2929
_Tasks.Enqueue(task);
30+
// note: don't use 'await' keyword for the 'task' because it may start the task in
31+
// another thread.
3032
while (!task.IsCompleted)
3133
{
3234
await Task.Yield();

src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@
290290
<Compile Include="StorageServices\CloudPageBlobObjectFactory.cs" />
291291
<Compile Include="StorageServices\SaveAzureVhdCommand.cs" />
292292
<Compile Include="StorageServices\StorageCredentialsFactory.cs" />
293-
<Compile Include="Strategies\MessageLoop.cs" />
293+
<Compile Include="Strategies\AsyncCmdletExtensions.cs" />
294+
<Compile Include="Strategies\Client.cs" />
295+
<Compile Include="Strategies\IAsyncCmdlet.cs" />
294296
<Compile Include="Strategies\ProgressReport.cs" />
295297
<Compile Include="Strategies\ShouldProcess.cs" />
296298
<Compile Include="Usage\GetAzureVMUsageCommand.cs" />
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Microsoft.Azure.Commands.Common.Strategies;
2+
using System;
3+
using System.Management.Automation;
4+
using System.Threading.Tasks;
5+
6+
namespace Microsoft.Azure.Commands.Compute.Strategies
7+
{
8+
static class AsyncCmdletExtensions
9+
{
10+
/// <summary>
11+
/// Note: the function must be called in the main PowerShell thread.
12+
/// </summary>
13+
/// <param name="cmdlet"></param>
14+
/// <param name="createAndStartTask"></param>
15+
public static void StartAndWait(this Cmdlet cmdlet, Func<IAsyncCmdlet, Task> createAndStartTask)
16+
{
17+
var asyncCmdlet = new AsyncCmdlet(cmdlet);
18+
asyncCmdlet.Scheduler.Wait(createAndStartTask(asyncCmdlet));
19+
}
20+
21+
sealed class AsyncCmdlet : IAsyncCmdlet
22+
{
23+
public SyncTaskScheduler Scheduler { get; } = new SyncTaskScheduler();
24+
25+
readonly Cmdlet _Cmdlet;
26+
27+
public AsyncCmdlet(Cmdlet cmdlet)
28+
{
29+
_Cmdlet = cmdlet;
30+
}
31+
32+
public void WriteVerbose(string message)
33+
=> Scheduler.BeginInvoke(() => _Cmdlet.WriteVerbose(message));
34+
35+
public Task<bool> ShouldProcessAsync(string target, string action)
36+
=> Scheduler.Invoke(() => _Cmdlet.ShouldProcess(target, action));
37+
}
38+
}
39+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Microsoft.Azure.Commands.Common.Authentication;
2+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
3+
using Microsoft.Azure.Commands.Common.Strategies;
4+
using Microsoft.Rest;
5+
6+
namespace Microsoft.Azure.Commands.Compute.Strategies
7+
{
8+
sealed class Client : IClient
9+
{
10+
public string SubscriptionId { get; }
11+
12+
IAzureContext Context { get; }
13+
14+
public Client(IAzureContext context)
15+
{
16+
Context = context;
17+
SubscriptionId = Context.Subscription.Id;
18+
}
19+
20+
public T GetClient<T>()
21+
where T : ServiceClient<T>
22+
=> AzureSession.Instance.ClientFactory.CreateArmClient<T>(
23+
Context, AzureEnvironment.Endpoint.ResourceManager);
24+
}
25+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Threading.Tasks;
2+
3+
namespace Microsoft.Azure.Commands.Compute.Strategies
4+
{
5+
interface IAsyncCmdlet
6+
{
7+
void WriteVerbose(string message);
8+
9+
Task<bool> ShouldProcessAsync(string target, string action);
10+
}
11+
}

src/ResourceManager/Compute/Commands.Compute/Strategies/ProgressReport.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,22 @@
1313
// ----------------------------------------------------------------------------------
1414

1515
using Microsoft.Azure.Commands.Common.Strategies;
16-
using System.Management.Automation;
1716

1817
namespace Microsoft.Azure.Commands.Compute.Strategies
1918
{
2019
sealed class ProgressReport : IProgressReport
2120
{
22-
readonly Cmdlet _Cmdlet;
21+
readonly IAsyncCmdlet _Cmdlet;
2322

24-
readonly MessageLoop _MessageLoop;
25-
26-
public ProgressReport(Cmdlet cmdlet, MessageLoop messageLoop)
23+
public ProgressReport(IAsyncCmdlet cmdlet)
2724
{
2825
_Cmdlet = cmdlet;
29-
_MessageLoop = messageLoop;
3026
}
3127

3228
public void Report<TModel>(ResourceConfig<TModel> config, double progress)
3329
where TModel : class
34-
=> _MessageLoop.BeginInvoke(() => _Cmdlet.WriteVerbose(progress == 0
30+
=> _Cmdlet.WriteVerbose(progress == 0
3531
? "Creating " + config.Name + " " + config.Strategy.Type + "..."
36-
: config.Name + " " + config.Strategy.Type + " is created."));
32+
: config.Name + " " + config.Strategy.Type + " is created.");
3733
}
3834
}

src/ResourceManager/Compute/Commands.Compute/Strategies/ShouldProcess.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,16 @@ namespace Microsoft.Azure.Commands.Compute.Strategies
2020
{
2121
internal sealed class ShouldProcess : IShouldProcess
2222
{
23-
readonly Cmdlet _Cmdlet;
23+
readonly IAsyncCmdlet _Cmdlet;
2424

25-
readonly MessageLoop _MessageLoop;
26-
27-
public ShouldProcess(Cmdlet cmdlet, MessageLoop messageLoop)
25+
public ShouldProcess(IAsyncCmdlet cmdlet)
2826
{
2927
_Cmdlet = cmdlet;
30-
_MessageLoop = messageLoop;
3128
}
3229

33-
public async Task<bool> ShouldCreate<TModel>(ResourceConfig<TModel> config, TModel model)
30+
public Task<bool> ShouldCreate<TModel>(ResourceConfig<TModel> config, TModel model)
3431
where TModel : class
35-
=> await _MessageLoop.Invoke(
36-
() => _Cmdlet.ShouldProcess(
37-
config.Name, VerbsCommon.New + " " + config.Strategy.Type));
32+
=> _Cmdlet.ShouldProcessAsync(
33+
config.Name, VerbsCommon.New + " " + config.Strategy.Type);
3834
}
3935
}

src/ResourceManager/Compute/Commands.Compute/VirtualMachine/Operation/NewAzureVMCommand.cs

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -161,35 +161,15 @@ public override void ExecuteCmdlet()
161161
switch (ParameterSetName)
162162
{
163163
case StrategyParameterSet:
164-
StrategyExecuteCmdlet();
164+
this.StartAndWait(StrategyExecuteCmdletAsync);
165165
break;
166166
default:
167167
DefaultExecuteCmdlet();
168168
break;
169169
}
170170
}
171171

172-
readonly MessageLoop _MessageLoop = new MessageLoop();
173-
174-
private sealed class Client : IClient
175-
{
176-
public string SubscriptionId { get; }
177-
178-
IAzureContext Context { get; }
179-
180-
public Client(IAzureContext context)
181-
{
182-
Context = context;
183-
SubscriptionId = Context.Subscription.Id;
184-
}
185-
186-
public T GetClient<T>()
187-
where T : ServiceClient<T>
188-
=> AzureSession.Instance.ClientFactory.CreateArmClient<T>(
189-
Context, AzureEnvironment.Endpoint.ResourceManager);
190-
}
191-
192-
public async Task StrategyExecuteCmdletAsync()
172+
async Task StrategyExecuteCmdletAsync(IAsyncCmdlet asyncCmdlet)
193173
{
194174
ResourceGroupName = ResourceGroupName ?? Name;
195175
VirtualNetworkName = VirtualNetworkName ?? Name;
@@ -252,14 +232,11 @@ public async Task StrategyExecuteCmdletAsync()
252232
client,
253233
target,
254234
new CancellationToken(),
255-
new ShouldProcess(this, _MessageLoop),
256-
new ProgressReport(this, _MessageLoop));
235+
new ShouldProcess(asyncCmdlet),
236+
new ProgressReport(asyncCmdlet));
257237
WriteObject(result);
258238
}
259239

260-
public void StrategyExecuteCmdlet()
261-
=> _MessageLoop.Wait(StrategyExecuteCmdletAsync());
262-
263240
public void DefaultExecuteCmdlet()
264241
{
265242
base.ExecuteCmdlet();

0 commit comments

Comments
 (0)