Skip to content

Commit df827b5

Browse files
committed
Cleanups to the code as requested
1 parent c0e3143 commit df827b5

File tree

3 files changed

+21
-117
lines changed

3 files changed

+21
-117
lines changed

src/Renci.SshNet.Tests/Classes/SshCommandTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ public async Task Test_Execute_Invalid_CommandAsync()
576576
await client.ConnectAsync(default);
577577

578578
var cmd = client.CreateCommand(";");
579-
await cmd.ExecuteAsync();
579+
await cmd.ExecuteAsync(default);
580580
var error = await new StreamReader(cmd.ExtendedOutputStream).ReadToEndAsync();
581581
if (!string.IsNullOrEmpty(error))
582582
{

src/Renci.SshNet/AsyncExtensions.cs

Lines changed: 14 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,97 +17,34 @@ public static class AsyncExtensions
1717
/// <param name="asyncResult">Async result we need to await on</param>
1818
/// <param name="endMethod">End method for the async function</param>
1919
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
20-
/// <param name="factory">Optional task factory to use</param>
21-
/// <param name="creationOptions">Optional task creation options to use</param>
22-
/// <param name="scheduler">Optional task schedule to use</param>
23-
internal static async Task FromAsync(
24-
IAsyncResult asyncResult,
25-
Action<IAsyncResult> endMethod,
26-
CancellationToken cancellationToken,
27-
TaskFactory factory,
28-
TaskCreationOptions creationOptions,
29-
TaskScheduler scheduler)
30-
{
31-
// Execute the task via APM
32-
factory = factory ?? Task.Factory;
33-
scheduler = scheduler ?? factory.Scheduler ?? TaskScheduler.Current;
34-
var asyncTask = factory.FromAsync(asyncResult, endMethod, creationOptions, scheduler);
35-
36-
// Create another task that completes as soon as cancellation is requested.
37-
// http://stackoverflow.com/a/18672893/1149773
38-
var tcs = new TaskCompletionSource<object>();
39-
cancellationToken.Register(() => tcs.TrySetCanceled(), false);
40-
var cancellationTask = tcs.Task;
41-
42-
// Create a task that completes when either the async operation completes,
43-
// or cancellation is requested.
44-
var readyTask = await Task.WhenAny(asyncTask, cancellationTask).ConfigureAwait(false);
45-
46-
// In case of cancellation, register a continuation to observe any unhandled
47-
// exceptions from the asynchronous operation (once it completes).
48-
// In .NET 4.0, unobserved task exceptions would terminate the process.
49-
if (readyTask == cancellationTask)
50-
{
51-
// If we have a wait handle, set it so the task will terminate
52-
var waitHandle = asyncResult.AsyncWaitHandle as EventWaitHandle;
53-
waitHandle?.Set();
54-
55-
// Now register the continuation as mentioned above
56-
await asyncTask.ContinueWith(_ => asyncTask.Exception,
57-
TaskContinuationOptions.OnlyOnFaulted |
58-
TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false);
59-
}
60-
}
61-
62-
/// <summary>
63-
/// Wrapper to convert a function from APM to TAP and supports cancellation tokens as seen here:
64-
/// https://stackoverflow.com/questions/24980427/task-factory-fromasync-with-cancellationtokensource
65-
/// </summary>
66-
/// <param name="asyncResult">Async result we need to await on</param>
67-
/// <param name="endMethod">End method for the async function</param>
68-
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
69-
/// <param name="factory">Optional task factory to use</param>
70-
/// <param name="creationOptions">Optional task creation options to use</param>
71-
/// <param name="scheduler">Optional task schedule to use</param>
20+
/// <param name="cancellationCallback">Callback to call when the task is cancelled</param>
7221
internal static async Task<TResult> FromAsync<TResult>(
7322
IAsyncResult asyncResult,
7423
Func<IAsyncResult, TResult> endMethod,
7524
CancellationToken cancellationToken,
76-
TaskFactory<TResult> factory,
77-
TaskCreationOptions creationOptions,
78-
TaskScheduler scheduler)
25+
Action cancellationCallback)
7926
{
8027
// Execute the task via APM
81-
factory = factory ?? Task<TResult>.Factory;
82-
scheduler = scheduler ?? factory.Scheduler ?? TaskScheduler.Current;
83-
var asyncTask = factory.FromAsync(asyncResult, endMethod, creationOptions, scheduler);
28+
var asyncTask = Task<TResult>.Factory.FromAsync(asyncResult, endMethod);
8429

8530
// Create another task that completes as soon as cancellation is requested.
8631
// http://stackoverflow.com/a/18672893/1149773
8732
var tcs = new TaskCompletionSource<TResult>();
88-
cancellationToken.Register(() => tcs.TrySetCanceled(), false);
8933
var cancellationTask = tcs.Task;
90-
91-
// Create a task that completes when either the async operation completes,
92-
// or cancellation is requested.
93-
var readyTask = await Task.WhenAny(asyncTask, cancellationTask).ConfigureAwait(false);
94-
95-
// In case of cancellation, register a continuation to observe any unhandled
96-
// exceptions from the asynchronous operation (once it completes).
97-
// In .NET 4.0, unobserved task exceptions would terminate the process.
98-
if (readyTask == cancellationTask)
34+
using (cancellationToken.Register(() => tcs.TrySetCanceled(), false))
9935
{
100-
// If we have a wait handle, set it so the task will terminate
101-
var waitHandle = asyncResult.AsyncWaitHandle as EventWaitHandle;
102-
waitHandle?.Set();
36+
// Create a task that completes when either the async operation completes,
37+
// or cancellation is requested.
38+
var readyTask = await Task.WhenAny(asyncTask, cancellationTask).ConfigureAwait(false);
10339

104-
// Now register the continuation as mentioned above
105-
await asyncTask.ContinueWith(_ => asyncTask.Exception,
106-
TaskContinuationOptions.OnlyOnFaulted |
107-
TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false);
108-
}
40+
// Call the cancellation callback if provided to cancel the operation
41+
if (readyTask == cancellationTask)
42+
{
43+
cancellationCallback();
44+
}
10945

110-
return await readyTask.ConfigureAwait(false);
46+
return await readyTask.ConfigureAwait(false);
47+
}
11148
}
11249
}
11350
}

src/Renci.SshNet/SshCommand.cs

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -363,52 +363,19 @@ public string Execute()
363363
/// Asynchronously run a command.
364364
/// </summary>
365365
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
366-
/// <param name="factory">The <see cref="System.Threading.Tasks.TaskFactory">TaskFactory</see> used to create the Task</param>
367-
/// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
368-
/// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
369-
/// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
370-
/// that is used to schedule the task that executes the end method.</param>
371366
/// <returns>Returns <see cref="Task{Int32}"/> as command execution status result.</returns>
372367
public Task<int> ExecuteAsync(
373-
CancellationToken cancellationToken = default(CancellationToken),
374-
TaskFactory<int> factory = null,
375-
TaskCreationOptions creationOptions = default(TaskCreationOptions),
376-
TaskScheduler scheduler = null)
368+
CancellationToken cancellationToken)
377369
{
378370
return AsyncExtensions.FromAsync(
379371
BeginExecute(),
380372
EndExecuteWithStatus,
381373
cancellationToken,
382-
factory,
383-
creationOptions,
384-
scheduler);
385-
}
386-
387-
/// <summary>
388-
/// Asynchronously run a command.
389-
/// </summary>
390-
/// <param name="commandText">The command text to execute</param>
391-
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
392-
/// <param name="factory">The <see cref="System.Threading.Tasks.TaskFactory">TaskFactory</see> used to create the Task</param>
393-
/// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
394-
/// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
395-
/// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
396-
/// that is used to schedule the task that executes the end method.</param>
397-
/// <returns>Returns <see cref="Task{Int32}"/> as command execution status result.</returns>
398-
public Task<int> ExecuteAsync(
399-
string commandText,
400-
CancellationToken cancellationToken = default(CancellationToken),
401-
TaskFactory<int> factory = null,
402-
TaskCreationOptions creationOptions = default(TaskCreationOptions),
403-
TaskScheduler scheduler = null)
404-
{
405-
return AsyncExtensions.FromAsync(
406-
BeginExecute(commandText, null, null),
407-
EndExecuteWithStatus,
408-
cancellationToken,
409-
factory,
410-
creationOptions,
411-
scheduler);
374+
() =>
375+
{
376+
UnsubscribeFromEventsAndDisposeChannel(_channel);
377+
_channel = null;
378+
});
412379
}
413380
#endif
414381

0 commit comments

Comments
 (0)