Skip to content

Commit 3717ec1

Browse files
author
Oren (electricessence)
committed
Added Cancellable items.
1 parent b1b92c0 commit 3717ec1

6 files changed

Lines changed: 396 additions & 6 deletions

File tree

ActionRunner.cs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Open.Threading
6+
{
7+
public class ActionRunner : ICancellable
8+
{
9+
public ActionRunner(Action action, TaskScheduler scheduler = null)
10+
{
11+
_action = action;
12+
_scheduler = scheduler; // No need to hold a refernce to the default, just keep it null.
13+
LastStart = DateTime.MaxValue;
14+
LastComplete = DateTime.MaxValue;
15+
}
16+
17+
public static ActionRunner Create(Action action, TaskScheduler scheduler = null)
18+
{
19+
return new ActionRunner(action, scheduler);
20+
}
21+
22+
public static ActionRunner Create<T>(Func<T> action, TaskScheduler scheduler = null)
23+
{
24+
return new ActionRunner(()=> { action(); }, scheduler);
25+
}
26+
27+
Action _action;
28+
protected TaskScheduler _scheduler;
29+
30+
protected int _count;
31+
public int Count
32+
{
33+
get { return _count; }
34+
}
35+
36+
public DateTime LastStart
37+
{
38+
get;
39+
protected set;
40+
}
41+
42+
public bool HasBeenRun
43+
{
44+
get
45+
{
46+
return LastStart < DateTime.Now;
47+
}
48+
}
49+
50+
public DateTime LastComplete
51+
{
52+
get;
53+
protected set;
54+
}
55+
56+
public bool HasCompleted
57+
{
58+
get
59+
{
60+
return LastComplete < DateTime.Now;
61+
}
62+
}
63+
64+
public Exception LastFault
65+
{
66+
get;
67+
protected set;
68+
}
69+
70+
public bool Cancel(bool onlyIfNotRunning)
71+
{
72+
return _task?.Value.Cancel(onlyIfNotRunning) ?? false;
73+
}
74+
75+
public bool Cancel()
76+
{
77+
return Cancel(false);
78+
}
79+
80+
public void Dispose()
81+
{
82+
Cancel();
83+
_action = null;
84+
}
85+
86+
Action GetAction()
87+
{
88+
var a = _action;
89+
if (a == null)
90+
throw new ObjectDisposedException(typeof(ActionRunner).ToString());
91+
return a;
92+
}
93+
94+
public bool IsScheduled
95+
{
96+
get
97+
{
98+
return _task?.Value.IsActive() ?? false;
99+
}
100+
}
101+
102+
/// <summary>
103+
/// Indiscriminately invokes the action.
104+
/// </summary>
105+
public void RunSynchronously()
106+
{
107+
GetAction().Invoke();
108+
}
109+
110+
// Use a Lazy to ensure only 1 time initialization.
111+
Lazy<CancellableTask> _task;
112+
CancellableTask Prepare(TimeSpan delay)
113+
{
114+
LastStart = DateTime.Now;
115+
var task = CancellableTask.Start(GetAction(), delay, _scheduler);
116+
task
117+
.OnFaulted(ex=>
118+
{
119+
LastFault = ex;
120+
})
121+
.OnFullfilled(() =>
122+
{
123+
LastComplete = DateTime.Now;
124+
Interlocked.Increment(ref _count);
125+
})
126+
.ContinueWith(t => {
127+
Interlocked.Exchange(ref _task, null);
128+
});
129+
return task;
130+
}
131+
132+
public CancellableTask Run()
133+
{
134+
return Defer(TimeSpan.Zero);
135+
}
136+
137+
public CancellableTask Defer(TimeSpan delay, bool clearSchedule = true)
138+
{
139+
if (clearSchedule) Cancel(true); // Don't cancel defered if already running.
140+
var task = LazyInitializer.EnsureInitialized(
141+
ref _task, () => new Lazy<CancellableTask>(()=>Prepare(delay))).Value;
142+
return task;
143+
}
144+
145+
public CancellableTask Defer(int millisecondsDelay, bool clearSchedule = true)
146+
{
147+
return Defer(TimeSpan.FromMilliseconds(millisecondsDelay), clearSchedule);
148+
}
149+
150+
}
151+
}

AsyncProcess.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ public virtual DateTime LatestCompleted
3434
protected set;
3535
}
3636

37+
public Exception LastFault
38+
{
39+
get;
40+
protected set;
41+
}
42+
3743
protected AsyncProcess(TaskScheduler scheduler = null)
3844
: base()
3945
{
@@ -70,10 +76,11 @@ protected virtual void Process(object progress)
7076
{
7177
//Contract.Assert(Interlocked.Increment(ref _processCount) == 1);
7278
Closure(p);
79+
SyncLock.Write(() => LatestCompleted = DateTime.Now);
7380
}
74-
catch
81+
catch(Exception ex)
7582
{
76-
SyncLock.Write(() => LatestCompleted = DateTime.Now);
83+
SyncLock.Write(() => LastFault = ex);
7784
}
7885
finally
7986
{
@@ -92,7 +99,7 @@ protected virtual Task EnsureProcess(bool once, TimeSpan? timeAllowedBeforeRefre
9299
|| timeAllowedBeforeRefresh.Value < DateTime.Now - LatestCompleted); // Or later?
93100
}, () => {
94101

95-
task = new Task((Action<object>)Process, new T());
102+
task = new Task(Process, new T());
96103
task.Start(Scheduler);
97104
InternalTask = task;
98105
Count++;
@@ -116,9 +123,9 @@ public bool IsRunning
116123
}
117124
}
118125

119-
public void Wait()
126+
public void Wait(bool once = true)
120127
{
121-
EnsureActive(true);
128+
EnsureActive(once);
122129
InternalTask?.Wait();
123130
}
124131

0 commit comments

Comments
 (0)