@@ -17,97 +17,34 @@ public static class AsyncExtensions
17
17
/// <param name="asyncResult">Async result we need to await on</param>
18
18
/// <param name="endMethod">End method for the async function</param>
19
19
/// <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>
72
21
internal static async Task < TResult > FromAsync < TResult > (
73
22
IAsyncResult asyncResult ,
74
23
Func < IAsyncResult , TResult > endMethod ,
75
24
CancellationToken cancellationToken ,
76
- TaskFactory < TResult > factory ,
77
- TaskCreationOptions creationOptions ,
78
- TaskScheduler scheduler )
25
+ Action cancellationCallback )
79
26
{
80
27
// 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 ) ;
84
29
85
30
// Create another task that completes as soon as cancellation is requested.
86
31
// http://stackoverflow.com/a/18672893/1149773
87
32
var tcs = new TaskCompletionSource < TResult > ( ) ;
88
- cancellationToken . Register ( ( ) => tcs . TrySetCanceled ( ) , false ) ;
89
33
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 ) )
99
35
{
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 ) ;
103
39
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
+ }
109
45
110
- return await readyTask . ConfigureAwait ( false ) ;
46
+ return await readyTask . ConfigureAwait ( false ) ;
47
+ }
111
48
}
112
49
}
113
50
}
0 commit comments