TPL Fire and Forget using a Separate Class - c#

I'm trying to implement fire and forget functionality, using the Task Parallel Library. With an inline call to Task.Factory.StartNew, everything works as expected. However, I want to move the Task.Factory.StartNew call into a separate class so that I can add logging, error handling, etc, and potentially upgrade the code in the future as better threading classes, etc are added to the .NET Framework, without duplicating code.
Below is a unit test that I would expect to pass, but that does not. I would appreciate help trying to figure out how to make this work.
[TestFixture]
public class ThreadingServiceFixture
{
public static bool methodFired = false;
[Test]
public void CanFireAndForgetWithThreadingService()
{
try
{
var service = new ThreadingService();
service.FireAndForget(() => methodFired = true);
var endTime = DateTime.Now.AddSeconds(1);
while(DateTime.Now < endTime)
{
//wait
}
Assert.IsTrue(methodFired == true);
}
finally
{
methodFired = false;
}
}
}
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action);
}
}

You're not executing the action, you're just returning it.
Try:
return Task.Factory.StartNew(() => action());

If is "fire and forget" you don't need to return the Task from the FireAndForget method, because the caller could get that Task and cancel it (strictly speaking the caller would "remember" of the call).
If you want to invoke this method from many services that do not inherit from a common ThreadingService you can implement an extension method via an interface.
public interface IFireAndForget
{
// no member needed.
}
public static class FireAndForgetExtensions
{
public static void FireAndForget(this IFireAndForget obj, Action action)
{
// pass the action, not a new lambda
Task.Factory.StartNew(action);
}
}
// using
public class ThreadingService : IFireAndForget
{
}
Also note the in your method you have to pass the action to the StartNew method insted of pass a lambda that return the action parameter.

You did not invoke the action in the ThreadingService
The code should read something like
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action.Invoke());
}
}
Additional note: testing state with a public field is evil. Think about repeatability, maintenance, running tests in different order. You should move bool methodFired inside the test. I would also assume there is a better technique to test this (but I am not sure which one).

Testing threaded code is hard.
Basing your tests on timing is a bad idea, they may become non-deterministic and you might observe erratic behavior on you build server. Imagine a tests that sometime passes and sometimes doesn't!
Your code has a bug, since you are not actually invoking the action.
But consider this variation:
[Test]
[TimeOut(5000)]
public void CanFireAndForgetWithThreadingService()
{
var service = new ThreadingService();
ManualResetEvent mre = new ManualRestEvent(bool); // I never remember what is the default...
service.FireAndForget(() => mre.Set() /*will release the test asynchroneously*/);
mre.WaitOne(); // blocks, will timeout if FireAndForget does not fire the action.
}
Yes, we are still using timing. But the test the timeout will happen only if the code breaks!
In all other scenarios, the test is absolutely predictable and takes a very short amount of time to execute, no waiting and praying for timing issues not to happen ;-)

Related

What's the right way to implement ValueTaskSource.SetCompleted

So we have this class implementing IValueTaskSource This code cannot be written as async-await because there's nothing to await on. We send a message to another running thread and get back a ValueTask that can be awaited by the caller to get the notification that the other thread has finished processing the message. However the other thread is pre-existing and already doing work. It receives the message by a completely other way; processes the message, then needs to tell the threadpool-origin thread that it finished. Thus; IValueTaskSource
There is no stock ValueTaskSource (not getting into whether or not there should be; however in this case a stock version would be of questionable utility). What we actully have looks very much like this:
class Message : IValueTaskSource {
public ValueTask Send()
{
/* how the message is sent is irrelevant */
return new ValueTask(this, 0);
}
private Action<object> continuation;
private object continuationState;
void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short _, ValueTaskSourceOnCompletedFlags __)
{
lock(this) {
if (GetStatus(_) == ValueTaskSourceStatus.Pending)
{
this.continuation = continuation;
this.continuationState = state;
return;
}
continuation(continuationState); /* Suspect */
}
}
public void SetCompleted()
{
lock (this)
{
/* set state completed omitted for brevity */
continuation?.Invoke(continuationState); /* Suspect */
}
}
}
I think I'm doing this wrong. Imagine a large chain of these; it seems like it would build up too much stack. In particular, the lines marked /* Suspect */ are exactly that; and ValueTaskSourceOnCompletionFlags is unused. Although it does have the nicety in that an exception thrown by continuation always goes somewhere; assuming that's even a real issue.
Right now, the code works because there are only three of them and the continuations that use them are very much thread agnostic which thread they are on.
Based on the link to ManualResetValueTaskSource provided by Stephen Cleary and the corresponding source code I was able to produce an answer.
ManualResetValueTaskSourceCore<T> provides a complete implementation of IValueTaskSource<T> and IValueTaskSource<T>. This is currently a case of there's no void implementation so create a void implementation with a dummy type. There's some generalized debate on whether bool or object is the best dummy type but I think it doesn't really matter because member padding of T will force alignment anyway.
So the answer is to forward all the methods.
public ValueTask Send()
{
/* how the message is sent is irrelevant */
return CraeteValueTask();
}
private ManualResetValueTaskSourceCore<object> taskSource;
private ValueTask CreateValueTask() => new ValueTask(this, taskSource.Version);
public ValueTaskSourceStatus GetStatus(short version) => taskSource.GetStatus(version);
public void OnCompleted(Action<object> continuation, object state, short version, ValueTaskSourceOnCompletedFlags flags) => taskSource.OnCompleted(continuation, state, version, flags);
public void SetCompleted() => taskSource.SetResult(null);
In this case each message is in its own object so there's no pooling. Doesn't matter. Calling the existing implementation is so much easier than trying to write down the smallest correct implementation that it's still the better way.
I'm pretty sure if I were pooling value task sources the correct way would be to call Reset() inside CreateValueTask().
Here is an example using the INotifyCompletion interface to get the notification, instead of the heavier IValueTaskSource+ValueTask mechanism. The Message class is amended with just one additional instance field, an Action, and it has become awaitable by exposing a GetAwaiter method. Each Message instance is intended to be awaited only once.
public class Message : INotifyCompletion
{
private static readonly Action _completedSentinel = new(() => { });
private Action _continuation;
public Message GetAwaiter() { return this; }
public bool IsCompleted
=> ReferenceEquals(Volatile.Read(ref _continuation), _completedSentinel);
public void OnCompleted(Action continuation)
{
Action original = Interlocked.CompareExchange(ref _continuation,
continuation, null);
if (original is null) return; // Normal case
if (ReferenceEquals(original, _completedSentinel))
continuation(); // Rare case
else
throw new InvalidOperationException("Double await");
}
public void GetResult() { }
public void SetCompleted()
{
Action continuation = Interlocked.Exchange(ref _continuation,
_completedSentinel);
if (continuation is null) return;
ThreadPool.QueueUserWorkItem(state => ((Action)state).Invoke(), continuation);
}
}
Online demo.
The static _completedSentinel field is used in order to resolve a race condition that might occur, between the thread that awaits and the thread that invokes the SetCompleted method. Normally the await will happen first, but the implementation above will not break if it happens after the SetCompleted, or even if the SetCompleted is invoked between the IsCompleted/OnCompleted calls (these are called by the async/await machinery).

Is there any way to know if a method is running being awaited from within the method?

I'm a university student but, since I like programming, I try to create a library of code that's been useful to me (something like a code base).
In the process of doing this, I started designing/writing an asynchronous method that's about to be used for interlocking a variable. My goal is to produce different result when this method is being awaited (runs synchronously) and when it isn't.
An example could be the following:
private int _lock;
public async Task<bool> Lock()
{
if (method_is_not_being_awaited)
return Interlocked.Exchange(ref _lock, 1) == 0;
while (0 != Interlocked.Exchange(ref _lock, 1)) {}
return true;
}
Is there any way to achieve such result? If yes, how?
ps: I know that I could make 2 different methods bool lock() and async Task<bool> lockAsync() but, that's not what I ask for
No, it is not possible to do what you want because method must return value before any operation on result (including await) can be performed. It is not specific to async methods but rather how all code behaves in C# (and pretty much any other language).
On other hand it is pretty easy to do something that very close to what you ask - synchronously return value as soon as one tries to await the result of the method: await is essentially just call to GetAwaiter on the result and you can wire it up to alter state of your method.
Note that you can't really know what to do if method ever awaited anyway - so while you can act at moment when await is called you really can't know in advance if you should start asynchronous processing. So the best you can achieve is to do nothing in synchronous part, start asynchronous processing anyway and instantly return result when await is called (aborting/ignoring asynchronous part of the method).
Details on implementing class that can be used as result can be found in https://www.codeproject.com/Articles/5274659/How-to-Use-the-Csharp-Await-Keyword-On-Anything and https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model.
Skeleton code below shows how to implement method that does nothing unless await is called:
class MyTask
{
public MyAwaitable GetAwaiter()
{
return new MyAwaitable();
}
}
class MyAwaitable : INotifyCompletion
{
public bool IsCompleted
{
get { return true; }
}
public int GetResult()
{
return 42; // this is our "result" from method.
}
public void OnCompleted (Action continuation)
{
// just run instantly - no need to save callback as this one is
// always "completed"
continuation();
}
}
MyTask F()
{
// if your really want you can start async operation here
// and somehow wire up MyAwaitable.IsComplete to terminate/abandon
// asynchronous part.
return new MyTask();
}

Force C# async tasks to be lazy?

I have a situation where I have an object tree created by a special factory. This is somewhat similar to a DI container, but not quite.
Creation of objects always happens via constructor, and the objects are immutable.
Some parts of the object tree may not be needed in a given execution and should be created lazily. So the constructor argument should be something that is just a factory for on-demand creation. This looks like a job for Lazy.
However, object creation may need to access slow resources and is thus always async. (The object factory's creation function returns a Task.) This means that the creation function for the Lazy would need to be async, and thus the injected type needs to be Lazy<Task<Foo>>.
But I'd rather not have the double wrapping. I wonder if it is possible to force a Task to be lazy, i.e. to create a Task that is guaranteed to not execute until it is awaited. As I understand it, a Task.Run or Task.Factory.StartNew may start executing at any time (e.g. if a thread from the pool is idle), even if nothing is waiting for it.
public class SomePart
{
// Factory should create OtherPart immediately, but SlowPart
// creation should not run until and unless someone actually
// awaits the task.
public SomePart(OtherPart eagerPart, Task<SlowPart> lazyPart)
{
EagerPart = eagerPart;
LazyPart = lazyPart;
}
public OtherPart EagerPart {get;}
public Task<SlowPart> LazyPart {get;}
}
I'm not sure exactly why you want to avoid using Lazy<Task<>>,, but if it's just for keeping the API easier to use, as this is a property, you could do it with a backing field:
public class SomePart
{
private readonly Lazy<Task<SlowPart>> _lazyPart;
public SomePart(OtherPart eagerPart, Func<Task<SlowPart>> lazyPartFactory)
{
_lazyPart = new Lazy<Task<SlowPart>>(lazyPartFactory);
EagerPart = eagerPart;
}
OtherPart EagerPart { get; }
Task<SlowPart> LazyPart => _lazyPart.Value;
}
That way, the usage is as if it were just a task, but the initialisation is lazy and will only incur the work if needed.
#Max' answer is good but I'd like to add the version which is built on top of Stephen Toub' article mentioned in comments:
public class SomePart: Lazy<Task<SlowPart>>
{
public SomePart(OtherPart eagerPart, Func<Task<SlowPart>> lazyPartFactory)
: base(() => Task.Run(lazyPartFactory))
{
EagerPart = eagerPart;
}
public OtherPart EagerPart { get; }
public TaskAwaiter<SlowPart> GetAwaiter() => Value.GetAwaiter();
}
SomePart's explicitly inherited from Lazy<Task<>> so it's clear that it's lazy and asyncronous.
Calling base constructor wraps lazyPartFactory to Task.Run to avoid long block if that factory needs some cpu-heavy work before real async part. If it's not your case, just change it to base(lazyPartFactory)
SlowPart is accessible through TaskAwaiter. So SomePart' public interface is:
var eagerValue = somePart.EagerPart;
var slowValue = await somePart;
Declaration:
private Lazy<Task<ServerResult>> _lazyServerResult;`
ctor()
{
_lazyServerResult = new Lazy<Task<ServerResult>>(async () => await
GetServerResultAsync())
}
Usage:
ServerResult result = await _lazyServerResult.Value;
Using the constructor for Task make the task lazy a.k.a not running until you say it to run, so you could do something like this:
public class TestLazyTask
{
private Task<int> lazyPart;
public TestLazyTask(Task<int> lazyPart)
{
this.lazyPart = lazyPart;
}
public Task<int> LazyPart
{
get
{
// You have to start it manually at some point, this is the naive way to do it
this.lazyPart.Start();
return this.lazyPart;
}
}
}
public static async void Test()
{
Trace.TraceInformation("Creating task");
var lazyTask = new Task<int>(() =>
{
Trace.TraceInformation("Task run");
return 0;
});
var taskWrapper = new TestLazyTask(lazyTask);
Trace.TraceInformation("Calling await on task");
await taskWrapper.LazyPart;
}
Result:
SandBox.exe Information: 0 : Creating task
SandBox.exe Information: 0 : Calling await on task
SandBox.exe Information: 0 : Task run
However I strongly recommend you to use Rx.NET and IObservable as in your case you will get way less troubles for handling less naive cases to start your task at the right moment.
Also it makes the code a bit cleaner in my opinion
public class TestLazyObservable
{
public TestLazyObservable(IObservable<int> lazyPart)
{
this.LazyPart = lazyPart;
}
public IObservable<int> LazyPart { get; }
}
public static async void TestObservable()
{
Trace.TraceInformation("Creating observable");
// From async to demonstrate the Task compatibility of observables
var lazyTask = Observable.FromAsync(() => Task.Run(() =>
{
Trace.TraceInformation("Observable run");
return 0;
}));
var taskWrapper = new TestLazyObservable(lazyTask);
Trace.TraceInformation("Calling await on observable");
await taskWrapper.LazyPart;
}
Result:
SandBox.exe Information: 0 : Creating observable
SandBox.exe Information: 0 : Calling await on observable
SandBox.exe Information: 0 : Observable run
To be more clear: The Observable here handle when to start the task, it is Lazy by default and will run the task everytime it is subscribed (here subscribe is used by the awaiter that enable the use of the await keyword).
You could, if you need to, make the task run only once every minute (or ever) and having its result published across all subscribers to save performance for instance, like in a real world app, all of this and many more is handled by observables.

Using Task.Run() for hardware interfacing thread invocations

I need to invoke a method that meets the following criteria.
The method may run for hours.
The method may interface with hardware.
The method may request user input (parameter values, confirmation, etc). The request should block the method until input has been received.
I have a prototype implementation that fulfills this criteria using the following design.
Assume a Form exists and contains a Panel.
The IntegerInput class is a UserControl with a TextBox and a Button.
public partial class IntegerInput : UserControl
{
public TaskCompletionSource<int> InputVal = new TaskCompletionSource<int>(0);
public IntegerInput()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int val = 0;
Int32.TryParse(textBox1.Text, out val);
InputVal.SetResult(val);
}
}
The Form1UserInput class is instanced by Form1. The container is a Panel set by Form1 before being provided to the invoking class.
public interface IUserInput
{
Task<int> GetInteger();
}
public class Form1UserInput : IUserInput
{
public Control container;
private IntegerInput integerInput = new IntegerInput();
public IntegerInput IntegerInput { get { return integerInput; } }
public async Task<int> GetInteger()
{
container.Invoke(new Action(() =>
{
container.Controls.Clear();
container.Controls.Add(integerInput);
}));
await integerInput.InputVal.Task;
return integerInput.InputVal.Task.Result;
}
}
The Demo class contains the method I want to invoke.
public class Demo
{
public IUserInput ui;
public async void MethodToInvoke()
{
// Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
// Interface with hardware some more...
}
public async void AnotherMethodToInvoke()
{
// Interface with hardware...
// Block waiting on multiple input
int val1 = await ui.getInteger();
int val2 = await ui.getInteger();
// Interface with hardware...
}
}
This is a rough outline of what the invoking class looks like. The call to Task.Run() is accurate for my prototype.
public class Invoker
{
public async Task RunTestAsync(IUserInput ui)
{
object DemoInstance = Activator.CreateInstance(typeof(Demo));
MethodInfo method = typeof(Demo).GetMethod("MethodToInvoke");
object[] args = null;
((IUserInput)DemoInstance).ui = ui;
var t = await Task.Run(() => method.Invoke(DemoInstance, args));
// Report completion information back to Form1
}
}
The Form1 controller class instances the Invoker and calls RunTestAsync passing in an instance of Form1UserInput.
I am aware of some concerns about long running Tasks that may block and what that would mean for ThreadPool resources. However, the ability to invoke multiple methods at once is not provided by the application I am building. It's possible that the application may provide some other limited functionality while the invoked method is running but the current requirements do not specify such functionality in detail. I anticipate that there would only be one long running thread in service at any time.
Is the use of Task.Run() for this type of method invocation a reasonable implementation? If not, what would a more reasonable implementation be that provides for the required criteria? Should I consider a dedicated thread outside of the ThreadPool for this invocation?
Is the use of Task.Run() for this type of method invocation a reasonable implementation?
Assuming that your "interface with hardware" can only be done using synchronous APIs, then yes, Task.Run is fine for that.
However, I would change when it's called. Right now, Task.Run is wrapping an async void method that executes on the thread pool (and uses Invoke to jump back on the UI thread). These are each problematic: Task.Run over async void will seem to complete "early" (i.e., at the first await); and using Invoke indicates that there's some tight coupling going on (UI calls background service which calls UI).
I would replace the async void with async Task and also change where Task.Run is used to avoid Invoke:
public async Task<int> GetInteger()
{
container.Controls.Clear();
container.Controls.Add(integerInput);
// Note: not `Result`, which will wrap exceptions.
return await integerInput.InputVal.Task;
}
public async Task MethodToInvokeAsync()
{
await Task.Run(...); // Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
await Task.Run(...); // Interface with hardware some more...
}
var t = await (Task)method.Invoke(DemoInstance, args);

C# Unit Testing - Thread.Sleep(x) - How to Mock the System Clock

I have to test a method which does a certain amount of work after an interval.
while (running)
{
...
// Work
...
Thread.Sleep(Interval);
}
Interval is passed in as a parameter to the class so I can just pass in 0 or 1 but I was interested as to how to mock the system clock if this wasn't the case.
In my test I'd like to be able to simply set the time forward by TimeSpan Interval and have the thread wake up.
I've never written tests for code which acts upon the executing thread before and I'm sure there are some pitfalls to avoid - please feel free to elaborate on what approach you use.
Thanks!
If you do not wish to test the fact that the thread actually sleeps, a more straightforward approach (and one that is possible) is to have an ISleepService. You can then mock this out, and then not sleep in your tests, but have an implementation that does cause a Thread.Sleep in your production code.
ISleepService sleepService = Container.Resolve<ISleepService>();
..
while (running)
{
...
// Work
...
sleepService.Sleep(Interval);
}
Example using Moq:
public interface ISleepService
{
void Sleep(int interval);
}
[Test]
public void Test()
{
const int Interval = 1000;
Mock<ISleepService> sleepService = new Mock<ISleepService>();
sleepService.Setup(s => s.Sleep(It.IsAny<int>()));
_container.RegisterInstance(sleepService.Object);
SomeClass someClass = _container.Resolve<SomeClass>();
someClass.DoSomething(interval: Interval);
//Do some asserting.
//Optionally assert that sleep service was called
sleepService.Verify(s => s.Sleep(Interval));
}
private class SomeClass
{
private readonly ISleepService _sleepService;
public SomeClass(IUnityContainer container)
{
_sleepService = container.Resolve<ISleepService>();
}
public void DoSomething(int interval)
{
while (true)
{
_sleepService.Sleep(interval);
break;
}
}
}
Update
On a design\maintenance note, if it is painful to change the constructor of "SomeClass", or to add Dependency Injection points to the user of the class, then a service locator type pattern can help out here, e.g.:
private class SomeClass
{
private readonly ISleepService _sleepService;
public SomeClass()
{
_sleepService = ServiceLocator.Container.Resolve<ISleepService>();
}
public void DoSomething(int interval)
{
while (true)
{
_sleepService.Sleep(interval);
break;
}
}
}
You can't really mock the system clock.
If you need to be able to alter the suspend behavior of code like this, you will need to refactor it so that you are not calling Thread.Sleep() directly.
I would create a singleton service, which could be injected into the application when it's under test. The singleton service would have to include methods to allow some external caller (like a unit test) to be able to cancel a sleep operation.
Alternatively, you could use a Mutex or WaitHandle object's WaitOne() method which has a timeout parameter. This way you could trigger the mutex to cancel the "sleep" or let it timeout:
public WaitHandle CancellableSleep = new WaitHandle(); // publicly available
// in your code under test use this instead of Thread.Sleep()...
while( running ) {
// .. work ..
CancellableSleep.WaitOne( Interval ); // suspends thread for Interval timeout
}
// external code can cancel the sleep by doing:
CancellableSleep.Set(); // trigger the handle...

Categories