Skip to content

Commit 6afe585

Browse files
author
Oren (electricessence)
committed
Updated extensions.
1 parent 3717ec1 commit 6afe585

3 files changed

Lines changed: 101 additions & 44 deletions

File tree

CancellableTask.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public static CancellableTask Start(TimeSpan delay, Action action = null, TaskSc
9494
{
9595
cancellable.ContinueWith(t => cancellable.Cancel()); // If this is arbitrarily run before the delay, then cancel the delay.
9696
Delay(delay, token)
97-
.OnFullfilled(() => cancellable.Start(scheduler));
97+
.OnFullfilled(() => cancellable.EnsureStarted(scheduler));
9898
}
9999
}
100100

Open.Threading.csproj

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
Part of the "Open" set of libraries.</Description>
1111
<PackageLicenseUrl>https://github.com/electricessence/Open.Threading/blob/master/LISCENSE.md</PackageLicenseUrl>
1212
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
13-
<Version>1.1.0</Version>
13+
<Version>1.1.1</Version>
1414
<AssemblyVersion>1.0.0.1</AssemblyVersion>
1515
<FileVersion>1.0.0.1</FileVersion>
1616
<Copyright>https://github.com/electricessence/Open.Threading/blob/master/LISCENSE.md</Copyright>
@@ -24,6 +24,13 @@ Part of the "Open" set of libraries.</Description>
2424
<Compile Remove="AsyncReadWriteModificationSynchronizer.cs" />
2525
</ItemGroup>
2626

27+
<ItemGroup>
28+
<None Remove=".git" />
29+
<None Remove=".gitignore" />
30+
<None Remove="LISCENSE.md" />
31+
<None Remove="README.md" />
32+
</ItemGroup>
33+
2734
<ItemGroup>
2835
<PackageReference Include="Open.Diagnostics" Version="1.0.1" />
2936
<PackageReference Include="Open.Threading.ReadWrite" Version="1.0.1" />

TaskExtensions.cs

Lines changed: 92 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ namespace Open.Threading
55
{
66
public static class TaskExtensions
77
{
8+
/// <summary>
9+
/// Returns true if the target Task has not yet run, is waiting, or is running, else returns false.
10+
/// </summary>
811
public static bool IsActive(this Task target)
912
{
1013
if (target == null)
@@ -18,83 +21,130 @@ public static bool IsActive(this Task target)
1821
case TaskStatus.WaitingForChildrenToComplete:
1922
case TaskStatus.WaitingToRun:
2023
return true;
21-
case TaskStatus.Canceled:
22-
case TaskStatus.Faulted:
23-
case TaskStatus.RanToCompletion:
24-
return false;
24+
//case TaskStatus.Canceled:
25+
//case TaskStatus.Faulted:
26+
//case TaskStatus.RanToCompletion:
27+
// return false;
2528
}
2629

2730
return false;
2831
}
2932

30-
31-
32-
public static Task OnFullfilled(this Task target, Action action)
33+
/// <summary>
34+
/// Checks the status of the task and attempts to start it if waiting to start (TaskStatus.Created).
35+
/// </summary>
36+
/// <param name="scheduler">Optional scheduler to use.</param>
37+
/// <returns>True if start attempt was successful.</returns>
38+
public static bool EnsureStarted(this Task target, TaskScheduler scheduler = null)
3339
{
34-
return target.ContinueWith(task =>
35-
{
36-
if (task.IsCompleted) action();
37-
});
38-
}
40+
if(target==null) throw new NullReferenceException();
3941

40-
public static Task OnFullfilled<T>(this Task target, Func<T> action)
41-
{
42-
return target.ContinueWith(task =>
42+
if(target.Status==TaskStatus.Created)
4343
{
44-
if (task.IsCompleted) action();
45-
});
44+
try
45+
{
46+
if (scheduler == null)
47+
target.Start();
48+
else
49+
target.Start(scheduler);
50+
51+
return true;
52+
}
53+
catch(InvalidOperationException)
54+
{
55+
// Even though we've checked the status, it's possible it could have been started. We can't guarantee proper handling without a trap here.
56+
if (target.Status == TaskStatus.Created)
57+
throw; // Something wierd must have happened if we arrived here.
58+
}
59+
}
60+
61+
return false;
4662
}
4763

48-
public static Task<T> OnFullfilled<T>(this Task<T> target, Action<T> action)
64+
/// <summary>
65+
/// Utility method that can be chained with other methods for reacting to Task results. Only invokes the action if completed and not cancelled.
66+
/// </summary>
67+
/// <typeparam name="TTask">The return type is the same as the target.</typeparam>
68+
/// <param name="action">The action to perform if fullfulled.</param>
69+
/// <returns>The target object. Allows for method chaining.</returns>
70+
public static TTask OnFullfilled<TTask>(this TTask target, Action action)
71+
where TTask : Task
4972
{
50-
return target.ContinueWith(task =>
73+
target.ContinueWith(task =>
5174
{
52-
if (task.IsCompleted) action(task.Result);
53-
return task.Result;
75+
if (task.IsCompleted && !task.IsCanceled) action();
5476
});
77+
78+
return target;
5579
}
5680

57-
// Tasks don't behave like promises so even though this seems like we should call this "Catch", it's not doing that and a real catch statment needs to be wrapped around a wait call.
58-
public static Task OnFaulted(this Task target, Action<Exception> action)
81+
/// <summary>
82+
/// Utility method that can be chained with other methods for reacting to Task results. Only invokes the action if completed and not cancelled.
83+
/// </summary>
84+
/// <typeparam name="TTask">The return type is the same as the target.</typeparam>
85+
/// <param name="action">The action to perform if fullfulled.</param>
86+
/// <returns>The target object. Allows for method chaining.</returns>
87+
public static TTask OnFullfilled<TTask,T>(this TTask target, Func<T> action)
88+
where TTask : Task
5989
{
60-
return target.ContinueWith(task =>
90+
target.ContinueWith(task =>
6191
{
62-
if (task.IsFaulted) action(task.Exception);
92+
if (task.IsCompleted && !task.IsCanceled) action();
6393
});
94+
95+
return target;
6496
}
6597

66-
public static Task<T> OnFaulted<T>(this Task<T> target, Action<Exception> action)
98+
/// <summary>
99+
/// Utility method that can be chained with other methods for reacting to Task results. Only invokes the action if faulted.
100+
/// </summary>
101+
/// <typeparam name="TTask">The return type is the same as the target.</typeparam>
102+
/// <param name="action">The action to perform if faulted.</param>
103+
/// <returns>The target object. Allows for method chaining.</returns>
104+
public static TTask OnFaulted<TTask>(this TTask target, Action<Exception> action)
105+
where TTask : Task
67106
{
68-
return target.ContinueWith(task =>
107+
target.ContinueWith(task =>
69108
{
70109
if (task.IsFaulted) action(task.Exception);
71-
return task.Result;
72110
});
73-
}
74111

75-
public static Task OnCancelled(this Task target, Action action)
76-
{
77-
return target.ContinueWith(task =>
78-
{
79-
if (task.IsCanceled) action();
80-
});
112+
return target;
81113
}
82114

83-
public static Task<T> OnCancelled<T>(this Task<T> target, Action action)
115+
116+
/// <summary>
117+
/// Utility method that can be chained with other methods for reacting to Task results. Only invokes the action if cancelled.
118+
/// </summary>
119+
/// <typeparam name="TTask">The return type is the same as the target.</typeparam>
120+
/// <param name="action">The action to perform if cancelled.</param>
121+
/// <returns>The target object. Allows for method chaining.</returns>
122+
public static TTask OnCancelled<TTask>(this TTask target, Action action)
123+
where TTask : Task
84124
{
85-
return target.ContinueWith(task =>
125+
target.ContinueWith(task =>
86126
{
87-
if (task.IsCanceled) action();
88-
return task.Result;
127+
if (!task.IsCanceled) action();
89128
});
129+
130+
return target;
90131
}
91132

92-
public static Task OnCancelled<T>(this Task target, Func<T> action)
133+
/// <summary>
134+
/// Utility method that can be chained with other methods for reacting to Task results. Only invokes the action if cancelled.
135+
/// </summary>
136+
/// <typeparam name="TTask">The return type is the same as the target.</typeparam>
137+
/// <param name="action">The action to perform if cancelled.</param>
138+
/// <returns>The target object. Allows for method chaining.</returns>
139+
public static TTask OnCancelled<TTask, T>(this TTask target, Func<T> action)
140+
where TTask : Task
93141
{
94-
return target.ContinueWith(task =>
142+
target.ContinueWith(task =>
95143
{
96-
if (task.IsCanceled) action();
144+
if (!task.IsCanceled) action();
97145
});
146+
147+
return target;
98148
}
99149

100150
}

0 commit comments

Comments
 (0)