-
Notifications
You must be signed in to change notification settings - Fork 0
/
AsyncOp.cs
60 lines (51 loc) · 1.74 KB
/
AsyncOp.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Threading;
using System.Threading.Tasks;
namespace UtilClasses
{
public class AsyncOp<T>
{
Task<T> _pendingTask = null;
CancellationTokenSource _pendingCts = null;
public Task<T> PendingTask => _pendingTask;
public void Cancel()
{
if (_pendingTask != null && !_pendingTask.IsCompleted)
_pendingCts.Cancel();
}
public Task<T> RunAsync(Func<CancellationToken, Task<T>> routine, CancellationToken token)
{
var oldTask = _pendingTask;
var oldCts = _pendingCts;
var thisCts = CancellationTokenSource.CreateLinkedTokenSource(token);
Func<Task<T>> startAsync = async () =>
{
// await the old task
if (oldTask != null && !oldTask.IsCompleted)
{
oldCts.Cancel();
try
{
await oldTask;
}
catch (System.Exception ex)
{
while (ex is AggregateException)
ex = ex.InnerException;
if (!(ex is System.OperationCanceledException))
throw;
}
}
// run and await this task
return await routine(thisCts.Token);
};
_pendingCts = thisCts;
_pendingTask = Task.Factory.StartNew(
startAsync,
_pendingCts.Token,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext()).Unwrap();
return _pendingTask;
}
}
}