Mock PeriodicTimer for UnitTests - c#

My class is using PeriodicTimer . I want to mock its time in unit tests. Is it possible?
I can set up the class to have a shorter period but that's not the best practice for unit testing.
Nsubstitute example is preferable, but does not really matter.
Maybe it's possible to make a wrapper, however, ValueTask is a bit more tricky. Maybe I need to dig into IValueTaskSource. But maybe someone has a solution?
The code I want to test:
public class Example : BackgroundService
{
private readonly PeriodicTimer _timer;
public Example(IConfiguration configuration)
{
_timer = new PeriodicTimer(TimeSpan.Parse(configuration["Interval"]));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (await _timer.WaitForNextTickAsync(stoppingToken)) // I want to simulate this without waiting for real time
{
// Do something
}
}
}

The wrapper is the way to go, and it should be a dependency for your class.
Given these types
public interface IPeriodicTimer : IDisposable
{
ValueTask<bool> WaitForNextTickAsync (CancellationToken cancellationToken = default);
}
public sealed class StandardPeriodicTimer : IPeriodicTimer
{
private PeriodicTimer _actualTimer;
public StandardPeriodicTimer(TimeSpan timeSpan)
=> _actualTimer = new PeriodicTimer(timeSpan);
public async ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken = default)
=> await _actualTimer.WaitForNextTickAsync(cancellationToken);
public void Dispose() => _actualTimer.Dispose();
}
public class YourDependentClass
{
public YourDependentClass(IPeriodicTimer timer) => _timer = timer;
...
}
You can initialize a YourDependentClass via newing it up, or via dependency injection in production code.
var dependent = new YourDependentClass(new StandardPeriodicTimer(TimeSpan.FromSeconds(1)));
To support the tests, you can create a stub that simply returns true every time without any delay between.
public sealed class TestPeriodicTimer : IPeriodicTimer
{
public async ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken = default)
=> await Task.FromResult(true);
public void Dispose()
{}
}
When you use this stub, we're assuming that somehow the timer stops based on some internal condition in the dependent class.
[Test]
public void TestTheDependentClass()
{
// arrange
var timer = new TestPeriodicTimer();
var dependent = new YourDependentClass(timer);
// act
dependent.DoSomething();
// assert
// method exits because timer loop is done, timer disposed, etc.
...
}
Now, it could get a little trickier if you want the timer to fire a certain number of times, and to run assertions for each tick of the timer. You can either switch from a stub to NSubstitute as you suggest, or carry your stub a step further in its implementation.
But, it gets trickier still. The assertions should be about the state of the dependent after the dependent gets a return value for WaitForNextTickAsync. That means
upon the very first call to WaitForNextTickAsync you do nothing
on all subsequent calls but the final one you do assertions after the state changes
and finally, you have to do assertions when the timer is disposed
I'll make this make sense. 😀
The typical periodic timer is called in a loop. Let's say you call a method on your dependent that has this loop.
while (await _timer.WaitForNextTickAsync())
{
// some work
...
}
Furthermore, let's say in your test code you want to assert on the state of the dependency after each time // some work happens, not before.
And finally, the test run has to be finite. That means it must run a certain number of times, or the dependent must somehow exit the loop early. Let's code for the former problem.
public sealed class TestPeriodicTimer : IPeriodicTimer
{
private readonly int _numberOfExpectedTicks;
private int _tickNumber;
// our list of assertions...
// we assert for tick 1 on the second call to WaitForNextTickAsync
// we assert for tick 2 on the third call to WaitForNextTickAsync
// etc.
// so let's emulate a list that "starts" at index 2 instead of 0 to
// avoid some confusing code later
private readonly List<Action<int, bool>> _assertions = new() { null, null };
public TestPeriodicTimer(int numberOfTicks) => _numberOfExpectedTicks = numberofTicks.
// this is how we know what to assert when...
public void AddAssertionsCallback(Action<int, bool> action)
=> _actions.Add(action);
public async ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken = default)
{
// get result for current tick
var result = await Task.FromResult(_numberOfExpectedTicks == ++_tickNumber);
if (_tickNumber != 1)
{
// assert for the prior tick
var assertedTickNumber = _tickNumber - 1;
_assertions[_tickNumber](_assertedTickNumber, result);
}
return result;
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
// assert for the final tick
_assertions[_tickNumber + 1](_tickNumber, result);
}
private bool _disposed;
}
Ok, now we can finally code an expressive test.
[Test]
public void TestThreeTicksOfTheTimerInYourDependentClass()
{
// arrange
var timer = new TestPeriodicTimer(3);
var dependent = new YourDependentClass(timer);
dependent.AddAssertionsCallback((tickNumber, isFinalTick) =>
{
// assertions you expect to be true for tick 1 (actually
// the second call to WatiForNextTickAsync)
...
// and just to make sure...
Assert.IsTrue(tickNumber, 1);
Assert.IsFalse(isFinalTick);
});
dependent.AddAssertionsCallback((tickNumber, isFinalTick) =>
{
// assertions you expect to be true for tick 2 (actually
// the third call to WatiForNextTickAsync)
...
// and just to make sure...
Assert.IsTrue(tickNumber, 2);
Assert.IsFalse(isFinalTick);
});
dependent.AddAssertionsCallback((tickNumber, isFinalTick) =>
{
// assertions you expect to be true for tick 3 (actually
// the call to Dispose(), because Dispose() happens after
// tick 3's work
...
// and just to make sure...
Assert.IsTrue(tickNumber, 3);
Assert.IsTrue(isFinalTick);
});
// act
dependent.DoSomething();
timer.Dispose();
// assert
// place any final assertions here as usual
}
This test says I want exactly 3 ticks to occur with the final (third) tick to of course be the last.
Wow. that was a lot of work. But this gives you a way to
not sleep/block during a test
test assertions for each and every tick if desired
A further improvement would be to share assertions across ticks, etc.

Related

How can I ensure coverage of threaded code

I am trying to write a unit test that can hit a piece of threaded code 100% of the time for code coverage. The code can ONLY be reached in the context of a threaded application, and is engineered to be hit only once for every object instance in order to minimize lock time expense.
As a simplified example:
public class Example
{
private readonly object lockObject = new object();
private int? objectToInit = null;
public void EnsureObjectInit()
{
//To minimize hitting the lock code, the object is checked first.
if (!objectToInit.HasValue)
{
lock (lockObject)
{
//Then it is checked once more to ensure that it wasn't initiazlized
//before the lock was hit.
if (objectToInit.HasValue)
{
//This block can only be executed if a second thread is able to
//get to the lock before the first can initialize the object.
return;
}
objectToInit = 0;
}
}
}
}
To get code coverage to hit the code inside the second if statement, I've tried code like this:
[TestClass]
public class ExampleTest
{
[Test Method]
public void async MyTest()
{
Example example = new Example();
void runTask()
{
example.EnsureObjectInit();
}
//I've tried increasing the number of threads, but it doesn't make
//it hit the noted code any more consistently.
List<Task> tasks = new List<Task>(2);
tasks.Add(Task.Run(runTask));
tasks.Add(Task.Run(runTask));
await Task.WhenAll(tasks);
... perform extra validation ...
}
}
But code coverage fails to reach the inner if block at least 50% of the time.
Is there any way to force the unit tested code to stop the first thread before initializing the object so that the second thread can get into the first "if" block?
It's a bit of a hack, but you could use reflection to get the lockObject from the Example class instance. Then lock it manually in the ExampleTest method. NOTE: this is a highly couple test. If you change the name of the lock the test will fail.
private class LockExample
{
private readonly object lockObject = new object();
public void TestLock()
{
lock(lockObject)
{
//Do something
}
}
}
private class LockTest
{
public void Test()
{
var example = new LockExample();
var lockOjbect = typeof(LockExample).GetField("lockObject", BindingFlags.NonPublic|BindingFlags.Instance).GetValue(example);
lock (lockOjbect)
{
var task = Task.Run((Action)example.TestLock);
task.Wait(1); //allow the other thread to run
}
}
}
With a slight design change you can make your code easier testable: Extract the access to objectToInit.HasValue into a helper method like hasObjectToInitValue(). In your test, you can then override that method and can then test the scenario that the helper method on first call returns false and on second returns true.

Async version of Monitor.Pulse/Wait

I'm trying to optimize an async version of something similar (in basic funcionality) to the Monitor.Wait and Monitor.Pulse methods. The idea is to use this over an async method.
Requirements:
1) I have one Task running, that it is in charge of waiting until someone pulses my monitor.
2) That task may compute a complex (ie: time consuming) operation. In the meanwhile, the pulse method could be called several times without doing anything (as the main task is already doing some processing).
3) Once the main task finishes, it starts to Wait again until another Pulse comes in.
Worst case scenario is Wait>Pulse>Wait>Pulse>Wait..., but usually I have tenths/hundreds of pulses for every wait.
So, I have the following class (working, but I think it can be optimized a bit based on my requirements)
internal sealed class Awaiter
{
private readonly ConcurrentQueue<TaskCompletionSource<byte>> _waiting = new ConcurrentQueue<TaskCompletionSource<byte>>();
public void Pulse()
{
TaskCompletionSource<byte> tcs;
if (_waiting.TryDequeue(out tcs))
{
tcs.TrySetResult(1);
}
}
public Task Wait()
{
TaskCompletionSource<byte> tcs;
if (_waiting.TryPeek(out tcs))
{
return tcs.Task;
}
tcs = new TaskCompletionSource<byte>();
_waiting.Enqueue(tcs);
return tcs.Task;
}
}
The problem with the above class is the baggage I'm using just for synchronization. Since I will be waiting from one and only one thread, there is really no need to have a ConcurrentQueue, as I always have only one item in it.
So, I simplified it a bit and wrote the following:
internal sealed class Awaiter2
{
private readonly object _mutex = new object();
private TaskCompletionSource<byte> _waiting;
public void Pulse()
{
var w = _waiting;
if (w == null)
{
return;
}
lock (_mutex)
{
w = _waiting;
if (w == null)
{
return;
}
_waiting = null;
w.TrySetResult(1);
}
}
public Task Wait()
{
var w = _waiting;
if (w != null)
{
return w.Task;
}
lock (_mutex)
{
w = _waiting;
if (w != null)
{
return w.Task;
}
w = _waiting = new TaskCompletionSource<byte>();
return w.Task;
}
}
}
That new version is also working ok, but I'm still thinking it can be optimized a bit more, by removing the locks.
I'm looking for suggestions on how I can optimize the second version. Any ideas?
If you don't need the Wait() call to return a Task but are content with being able to await Wait() then you can implement a custom awaiter/awaitable.
See this link for an overview of the await pattern used by the compiler.
When implementing custom awaitables you will just be dealing with delegates and the actual "waiting" is left up to you. When you want to "await" for a condition it is often possible to keep a list of pending continuations and whenever the condition comes true you can invoke those continuations. You just need to deal with the synchronization coming from the fact that await can be called from arbitrary threads. If you know that you'll only ever await from one thread (say the UI thread) then you don't need any synchronization at all!
I'll try to give you a lock-free implementation but no guarantees that it is correct. If you don't understand why all race conditions are safe you should not use it and implement the async/await protocol using lock-statements or other techniques which you know how to debug.
public sealed class AsyncMonitor
{
private PulseAwaitable _currentWaiter;
public AsyncMonitor()
{
_currentWaiter = new PulseAwaitable();
}
public void Pulse()
{
// Optimize for the case when calling Pulse() when nobody is waiting.
//
// This has an inherent race condition when calling Pulse() and Wait()
// at the same time. The question this was written for did not specify
// how to resolve this, so it is a valid answer to tolerate either
// result and just allow the race condition.
//
if (_currentWaiter.HasWaitingContinuations)
Interlocked.Exchange(ref _currentWaiter, new PulseAwaitable()).Complete();
}
public PulseAwaitable Wait()
{
return _currentWaiter;
}
}
// This class maintains a list of waiting continuations to be executed when
// the owning AsyncMonitor is pulsed.
public sealed class PulseAwaitable : INotifyCompletion
{
// List of pending 'await' delegates.
private Action _pendingContinuations;
// Flag whether we have been pulsed. This is the primary variable
// around which we build the lock free synchronization.
private int _pulsed;
// AsyncMonitor creates instances as required.
internal PulseAwaitable()
{
}
// This check has a race condition which is tolerated.
// It is used to optimize for cases when the PulseAwaitable has no waiters.
internal bool HasWaitingContinuations
{
get { return Volatile.Read(ref _pendingContinuations) != null; }
}
// Called by the AsyncMonitor when it is pulsed.
internal void Complete()
{
// Set pulsed flag first because that is the variable around which
// we build the lock free protocol. Everything else this method does
// is free to have race conditions.
Interlocked.Exchange(ref _pulsed, 1);
// Execute pending continuations. This is free to race with calls
// of OnCompleted seeing the pulsed flag first.
Interlocked.Exchange(ref _pendingContinuations, null)?.Invoke();
}
#region Awaitable
// There is no need to separate the awaiter from the awaitable
// so we use one class to implement both parts of the protocol.
public PulseAwaitable GetAwaiter()
{
return this;
}
#endregion
#region Awaiter
public bool IsCompleted
{
// The return value of this property does not need to be up to date so we could omit the 'Volatile.Read' if we wanted to.
// What is not allowed is returning "true" even if we are not completed, but this cannot happen since we never transist back to incompleted.
get { return Volatile.Read(ref _pulsed) == 1; }
}
public void OnCompleted(Action continuation)
{
// Protected against manual invocations. The compiler-generated code never passes null so you can remove this check in release builds if you want to.
if (continuation == null)
throw new ArgumentNullException(nameof(continuation));
// Standard pattern of maintaining a lock free immutable variable: read-modify-write cycle.
// See for example here: https://blogs.msdn.microsoft.com/oldnewthing/20140516-00/?p=973
// Again the 'Volatile.Read' is not really needed since outdated values will be detected at the first iteration.
var oldContinuations = Volatile.Read(ref _pendingContinuations);
for (;;)
{
var newContinuations = (oldContinuations + continuation);
var actualContinuations = Interlocked.CompareExchange(ref _pendingContinuations, newContinuations, oldContinuations);
if (actualContinuations == oldContinuations)
break;
oldContinuations = actualContinuations;
}
// Now comes the interesting part where the actual lock free synchronization happens.
// If we are completed then somebody needs to clean up remaining continuations.
// This happens last so the first part of the method can race with pulsing us.
if (IsCompleted)
Interlocked.Exchange(ref _pendingContinuations, null)?.Invoke();
}
public void GetResult()
{
// This is just to check against manual calls. The compiler will never call this when IsCompleted is false.
// (Assuming your OnCompleted implementation is bug-free and you don't execute continuations before IsCompleted becomes true.)
if (!IsCompleted)
throw new NotSupportedException("Synchronous waits are not supported. Use 'await' or OnCompleted to wait asynchronously");
}
#endregion
}
You usually don't bother on which thread the continuations run because if they are async methods the compiler has already inserted code (in the continuation) to switch back to the right thread, no need to do it manually in every awaitable implementation.
[edit]
As a starting point for how a locking implementation can look I'll provide one using a lock-statement. It should be easy to replace it by a spinlock or some other locking technique. By using a struct as the awaitable it even has the advantage that it does no additional allocation except for the initial object. (There are of course allocations in the async/await framework in the compiler magic on the calling side, but you can't get rid of these.)
Note that the iteration counter will increment only for every Wait+Pulse pair and will eventually overflow into negative, but that is ok. We just need to bridge the time from the continuation beeing invoked until it can call GetResult. 4 billion Wait+Pulse pairs should be plenty of time for any pending continuations to call its GetResult method. If you don't want that risk you could use a long or Guid for a more unique iteration counter, but IMHO an int is good for almost all scenarios.
public sealed class AsyncMonitor
{
public struct Awaitable : INotifyCompletion
{
// We use a struct to avoid allocations. Note that this means the compiler will copy
// the struct around in the calling code when doing 'await', so for your own debugging
// sanity make all variables readonly.
private readonly AsyncMonitor _monitor;
private readonly int _iteration;
public Awaitable(AsyncMonitor monitor)
{
lock (monitor)
{
_monitor = monitor;
_iteration = monitor._iteration;
}
}
public Awaitable GetAwaiter()
{
return this;
}
public bool IsCompleted
{
get
{
// We use the iteration counter as an indicator when we should be complete.
lock (_monitor)
{
return _monitor._iteration != _iteration;
}
}
}
public void OnCompleted(Action continuation)
{
// The compiler never passes null, but someone may call it manually.
if (continuation == null)
throw new ArgumentNullException(nameof(continuation));
lock (_monitor)
{
// Not calling IsCompleted since we already have a lock.
if (_monitor._iteration == _iteration)
{
_monitor._waiting += continuation;
// null the continuation to indicate the following code
// that we completed and don't want it executed.
continuation = null;
}
}
// If we were already completed then we didn't null the continuation.
// (We should invoke the continuation outside of the lock because it
// may want to Wait/Pulse again and we want to avoid reentrancy issues.)
continuation?.Invoke();
}
public void GetResult()
{
lock (_monitor)
{
// Not calling IsCompleted since we already have a lock.
if (_monitor._iteration == _iteration)
throw new NotSupportedException("Synchronous wait is not supported. Use await or OnCompleted.");
}
}
}
private Action _waiting;
private int _iteration;
public AsyncMonitor()
{
}
public void Pulse(bool executeAsync)
{
Action execute = null;
lock (this)
{
// If nobody is waiting we don't need to increment the iteration counter.
if (_waiting != null)
{
_iteration++;
execute = _waiting;
_waiting = null;
}
}
// Important: execute the callbacks outside the lock because they might Pulse or Wait again.
if (execute != null)
{
// If the caller doesn't want inlined execution (maybe he holds a lock)
// then execute it on the thread pool.
if (executeAsync)
Task.Run(execute);
else
execute();
}
}
public Awaitable Wait()
{
return new Awaitable(this);
}
}
Here is my simple async implementation that I use in my projects:
internal sealed class Pulsar
{
private static TaskCompletionSource<bool> Init() => new TaskCompletionSource<bool>();
private TaskCompletionSource<bool> _tcs = Init();
public void Pulse()
{
Interlocked.Exchange(ref _tcs, Init()).SetResult(true);
}
public Task AwaitPulse(CancellationToken token)
{
return token.CanBeCanceled ? _tcs.Task.WithCancellation(token) : _tcs.Task;
}
}
Add TaskCreationOptions.RunContinuationsAsynchronously to the TCS for async continuations.
The WithCancellation can be omitted of course, if you do not need cancellations.
Because you only have one task ever waiting your function can be simplified to
internal sealed class Awaiter3
{
private volatile TaskCompletionSource<byte> _waiting;
public void Pulse()
{
var w = _waiting;
if (w == null)
{
return;
}
_waiting = null;
#if NET_46_OR_GREATER
w.TrySetResult(1);
#else
Task.Run(() => w.TrySetResult(1));
#endif
}
//This method is not thread safe and can only be called by one thread at a time.
// To make it thread safe put a lock around the null check and the assignment,
// you do not need to have a lock on Pulse, "volatile" takes care of that side.
public Task Wait()
{
if(_waiting != null)
throw new InvalidOperationException("Only one waiter is allowed to exist at a time!");
#if NET_46_OR_GREATER
_waiting = new TaskCompletionSource<byte>(TaskCreationOptions.RunContinuationsAsynchronously);
#else
_waiting = new TaskCompletionSource<byte>();
#endif
return _waiting.Task;
}
}
One behavior I did change. If you are using .NET 4.6 or newer use the code in the #if NET_46_OR_GREATER blocks, if under use the else blocks. When you call TrySetResult you could have the continuation synchronously run, this can cause Pulse() to take a long time to complete. By using TaskCreationOptions.RunContinuationsAsynchronously in .NET 4.6 or wrapping the TrySetResult in a Task.Run for pre 4.6 will make sure that Puse() is not blocked by the continuation of the task.
See the SO question Detect target framework version at compile time on how to make a NET_46_OR_GREATER definition that works in your code.
A simple way to do this is to use SemaphoreSlim which uses Monitor.
public class AsyncMonitor
{
private readonly SemaphoreSlim signal = new SemaphoreSlim(0, 1);
public void Pulse()
{
try
{
signal.Release();
}
catch (SemaphoreFullException) { }
}
public async Task WaitAsync(CancellationToken cancellationToken)
{
await signal.WaitAsync(cancellationToken).ConfigureAwait(false);
}
}

Asynchronous initialization and its unit testing

Background
I need some class to perform background initialization, which should start in constructor. Currently I'm using a Task which is started by constructor, and then all operations, depending on that initialization wait for that Task completion.
Please take a look at the following simplified example:
interface IEntry {}
interface IRepository
{
IQueryable<IEntry> Query { get; }
void Add(IEntry entry);
}
class PrefetchedRepository : IRepository
{
private readonly Task _prefetchingTask;
private readonly ICollection<IEntry> _entries = new List<IEntry>();
private readonly IRepository _underlyingRepository;
public PrefetchedRepository(IRepository underlyingRepository)
{
_underlyingRepository = underlyingRepository;
// Background initialization starts here
_prefetchingTask = Task.Factory.StartNew(Prefetch);
}
public IQueryable<IEntry> Query
{
get
{
EnsurePrefetchCompleted();
return _entries.AsQueryable();
}
}
public void Add(IEntry entry)
{
EnsurePrefetchCompleted();
_entries.Add(entry);
_underlyingRepository.Add(entry);
}
private void EnsurePrefetchCompleted()
{
_prefetchingTask.Wait();
}
private void Prefetch()
{
foreach (var entry in _underlyingRepository.Query)
{
_entries.Add(entry);
}
}
}
This works. The problem starts when I want to test initialization in Unit Test. I'm creating the instance and providing the mock of underlying repository. I want to ensure that all entries were fetched from the mock as expected.
[TestFixture]
public class PrefetchingRepositoryTests
{
[Test]
public void WhenInitialized_PrefetchingIsDone()
{
// Arrange
var underlyingRepositoryMock = A.Fake<IRepository>();
// Act
var target = new PrefetchedRepository(_underlyingRepository);
// Assert
underlyingRepositoryMock.CallsTo(r => r.Query).MustHaveHappened(Repeated.Exactly(1));
}
}
As you can imagine, most of the time fails, because actually initialization didn't started yet at the assertion point.
Questions
Question 1 - Initialization: Is there more elegant way of asynchronous initialization rather than starting task in constructor and waiting for it in all dependent operations?
Question 2 - Testing: I thought of 2 possible ways to solve race between the test and testee:
Using event handle to the test:
[Test]
public void WhenInitialized_PrefetchingIsDone()
{
// Arrange ...
var invokedEvent = new ManualResetEvent(false);
underlyingRepositoryMock.CallsTo(r => r.Query).Invokes(_ => invokedEvent.Set());
// Act ...
// Assert
Assert.True(invokedEvent.WaitOne(1000));
}
Exposing EnsurePrefetchCompleted method as internal and using it in the Unit Test (assuming usage of [assembly: InternalsVisibleTo("...")])
The problem with both solutions is that in case of failure time duration long (actually in the second case - it is limited by test timeout).
Is there any simpler way to do this kind of testing?
Extract the prefetch logic into a separate Prefetcher class and when testing mock the Prefetcher with something that does the fetching without the use of a separate thread.
This will allow you to do the white-box testing of your PrefetchedRepository which I see you are attempting to do with
underlyingRepositoryMock.CallsTo(r => r.Query).MustHaveHappened(Repeated.Exactly(1)); (I would never do white-box testing, but that's just me.)
Once you are done with your white box testing, you can then do black-box testing of your PrefetchedRepository, without concern as to how it works internally. (Whether it invokes other objects to do its job, how many times it invokes them, etc.) Therefore, your testing code will not need to guess the point in time when it is okay to check whether query has been invoked, because it will not be concerned at all with whether query was invoked or not. Essentially, your testing code will be testing against interface IRepository, not against class PrefetchedRepository.
Don't expose a instance which is in invalid state. Client code may often notice a delay when calling any members in PrefetchedRepository just because the underlying repository is slow. You're trying to be clever by hiding these details by hiding all the grotty waiting logic inside EnsurePrefetchCompleted which client code doesn't even know. But this may surprise the client why does even this takes a lot of time??
Better approach is to expose the Task in the public surface of the API and let the client code await it before it does anything with the repository instance.
Something like this:
class PrefetchedRepository : IRepository
{
private readonly Task _prefetchingTask;
private readonly ICollection<IEntry> _entries = new List<IEntry>();
private readonly IRepository _underlyingRepository;
public PrefetchedRepository(IRepository underlyingRepository)
{
_underlyingRepository = underlyingRepository;
// Background initialization starts here
_prefetchingTask = Task.Factory.StartNew(Prefetch);
}
public Task Initialization
{
get
{
return _prefetchingTask;
}
}
...
}
Then you could do
var repo = new PrefetchedRepository(someOtherSlowRepo);
await repo.Initialization;
//Then do whatever with the repo.
Of course delete that EnsurePrefetchCompleted method and all calls to it.
But I do understand this introduces the smell so-called Temporal Coupling.
Better design is to introduce a Factory which does this for you.
public class PrefetchedRepositoryFactory
{
public Task<IRepository> CreateAsync()
{
//someOtherSlowRepo can be a parameter or instance field of this class
var repo = new PrefetchedRepository(someOtherSlowRepo);
await repo.Initialization;
return repo;
}
}
Then you could simply do
var repo = await prefetchedRepositoryFactory.CreateAsync();
//Do whatever with repo.
If you do so, you don't have to take any special care for testing as you'll always have the fully constructed repository in hand.
You can await inside the Test methods; Most of the major unittesting frameworks supports async Task returning methods.

best solution to overcome threading issue on shared object

Using Task Parallel Library in .net 4.0, I want to know what is the best solution to this situation :
My code is starting a task that do a lot of long running steps (steps need to be done one after other).
I have an object Result that aggregate the result of each steps.
The result object is modified in the task ( so in the thread related to this task ).
I also have an web service where we can fetch the current Result object to see the progress of the task.
So the Result object is a share object between the task and the main thread of my code. What is the best approach to implement this to be sure I don't have threading issues and things like that ?
Here a sample of what i'm talking about. Just note that _doWork would not be a static like in the code, it will be a member in another class higher in the hierarchy.
using System.Threading.Tasks;
namespace ConsoleApplication
{
public class Step1Result
{
}
public class Step2Result
{
}
public class Result
{
public Step1Result Step1Result;
public Step2Result Step2Result;
}
class DoWork
{
public Result Result;
public DoWork()
{
Result = new Result();
}
public void Process()
{
// Execute Step 1
Result.Step1Result = Step1();
Result.Step2Result = Step2();
// Other Steps ( long - running )
}
public Step1Result Step1()
{
// Long running step that can takes minutes
return new Step1Result();
}
public Step2Result Step2()
{
// Long running step that can takes minutes
return new Step2Result();
}
}
class Program
{
private static DoWork _doWork;
static void Main(string[] args)
{
_doWork = new DoWork();
var task = Task.Factory.StartNew(() => _doWork.Process());
task.Wait();
}
// This method will be called from a web service at anytime.
static Result CalledFromWebService()
{
return _doWork.Result;
}
}
}
The trouble here is accessing _doWork.Result from both the Task and the Main thread. True ? What could be done to overcome this ?
I would change DoWork.Result property to GetCurrentResult() method and return each time a new copy of current operation result (you can copy object using MemberwiseClone). I dont see any need to share the same object.
Additionalty, I would use ReadWriteLockSlim. So DoWork class will look like this
class DoWork
{
private readonly Result _result;
private readonly ReadWriteLockSlim _lock = new ReadWriteLockSlim();
public DoWork()
{
_result = new Result();
}
public void Process()
{
// Execute Step 1
Step1Result st1result = Step1();
try
{
_lock.EnterWriteLock();
_result.Step1Result = st1result;
}
finally
{
_lock.ExitWriteLock();
}
Step2Result st2result = Step2();
try
{
_lock.EnterWriteLock();
_result.Step2Result = st2result;
}
finally
{
_lock.ExitWriteLock();
}
// Other Steps ( long - running )
}
public Step1Result Step1()
{
// Long running step that can takes minutes
return new Step1Result();
}
public Step2Result Step2()
{
// Long running step that can takes minutes
return new Step2Result();
}
public Result GetCurrentResult()
{
try
{
_lock.EnterReadLock();
return (Result)_result.MemberwiseCopy();
}
finally
{
_lock.ExitReadLock();
}
}
}
If I understand the problem correctly you don't have thread safety issues accessing the Result object.
As you say the steps have to be finished one after each other so you won't be able to run them concurrently.
So inside Process() you can start Step1 in a task, then .Continue with Step2 in another task etc
Therefore you have a single writer thread and no concurrency issues. In this scenario it doesn't matter if you have another thread accessing the
result if that's a read-only fetching thread
You would only need a concurrent collection like ConcurrentDictionary to store the result if you were accessing a collection from different threads.
You would only need a ReadWriteLockSlim if the steps are not run one after each other and you had more than one writer
Your only concern here is dirty reads of the Result object returned from CalledFromWebService. You could add boolean properties to your Result object and remove the need for locks like so:
public class Result
{
public volatile bool IsStep1Valid;
public Step1Result Step1Result;
public volatile bool IsStep2Valid;
public Step2Result Step2Result;
}
Assignment to boolean values are atomic, so you don't have to worry about dirty reads and writes. You could then use those boolean values in your Process method like so:
public void Process()
{
// Execute Step 1
Result.Step1Result = Step1();
Result.IsStep1Valid = true;
Result.Step2Result = Step2();
Result.IsStep2Valid = true;
// Other Steps ( long - running )
}
Notice that the assignment to IsStep1Valid is after the assignment to Step1Result this ensures that Step1Result has a value assigned to it from the Task before IsStep1Valid is set to true.
Now when you access the result in your main thread by calling CalledFromWebService you can simply do the following:
void MyCode() {
var result = Program.CalledFromWebService();
if (result.IsStep1Valid) {
// do stuff with result.Step1Result
} else {
// if need be notify the user that step 1 is not complete yet
}
if (result.IsStep2Valid) {
// do stuff with result.Step2Result
}
// etc.
}
Checking the value of IsStep1Valid before you try to access the Step1Result property ensures that you are not getting a dirty read of the Step1Result property.
Update: A separate web service will not have access to the result object in the windows service because they run in separate app domains. You will need to expose a web service from inside your windows service, and have the main thread of the windows service load the web service and call your background task. You don't have to publicly expose this web service. You can still host a web service in IIS or where ever you originally intended. It would simply call the web service hosted by the windows service.

How to initialize an object using async-await pattern

I'm trying to follow RAII pattern in my service classes, meaning that when an object is constructed, it is fully initialized. However, I'm facing difficulties with asynchronous APIs. The structure of class in question looks like following
class ServiceProvider : IServiceProvider // Is only used through this interface
{
public int ImportantValue { get; set; }
public event EventHandler ImportantValueUpdated;
public ServiceProvider(IDependency1 dep1, IDependency2 dep2)
{
// IDependency1 provide an input value to calculate ImportantValue
// IDependency2 provide an async algorithm to calculate ImportantValue
}
}
I'm also targeting to get rid of side-effects in ImportantValue getter, to make it thread-safe.
Now users of ServiceProvider will create an instance of it, subscribe to an event of ImportantValue change, and get the initial ImportantValue. And here comes the problem, with the initial value. Since the ImportantValue is calculated asynchronously, the class cannot be fully initialized in constructor. It may be okay to have this value as null initially, but then I need to have some place where it will be calculated first time. A natural place for that could be the ImportantValue's getter, but I'm targeting to make it thread-safe and with no side-effects.
So I'm basically stuck with these contradictions. Could you please help me and offer some alternative? Having value initialized in constructor while nice is not really necessary, but no side-effects and thread-safety of property is mandatory.
Thanks in advance.
EDIT: One more thing to add. I'm using Ninject for instantiation, and as far as I understand, it doesn't support async methods to create a binding. While approach with initiating some Task-based operation in constructor will work, I cannot await its result.
I.e. two next approaches (offered as answers so far) will not compile, since Task is returned, not my object:
Kernel.Bind<IServiceProvider>().ToMethod(async ctx => await ServiceProvider.CreateAsync())
or
Kernel.Bind<IServiceProvider>().ToMethod(async ctx =>
{
var sp = new ServiceProvider();
await sp.InitializeAsync();
})
Simple binding will work, but I'm not awaiting the result of asynchronous initialization started in constructor, as proposed by Stephen Cleary:
Kernel.Bind<IServiceProvider>().To<ServiceProvider>();
... and that's not looking good for me.
I have a blog post that describes several approaches to async construction.
I recommend the asynchronous factory method as described by Reed, but sometimes that's not possible (e.g., dependency injection). In these cases, you can use an asynchronous initialization pattern like this:
public sealed class MyType
{
public MyType()
{
Initialization = InitializeAsync();
}
public Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
await Task.Delay(100);
}
}
You can then construct the type normally, but keep in mind that construction only starts the asynchronous initialization. When you need the type to be initialized, your code can do:
await myTypeInstance.Initialization;
Note that if Initialization is already complete, execution (synchronously) continues past the await.
If you do want an actual asynchronous property, I have a blog post for that, too. Your situation sounds like it may benefit from AsyncLazy<T>:
public sealed class MyClass
{
public MyClass()
{
MyProperty = new AsyncLazy<int>(async () =>
{
await Task.Delay(100);
return 13;
});
}
public AsyncLazy<int> MyProperty { get; private set; }
}
One potential option would be to move this to a factory method instead of using a constructor.
Your factory method could then return a Task<ServiceProvider>, which would allow you to perform the initialization asynchronously, but not return the constructed ServiceProvider until ImportantValue has been (asynchronously) computed.
This would allow your users to write code like:
var sp = await ServiceProvider.CreateAsync();
int iv = sp.ImportantValue; // Will be initialized at this point
This is a slight modification to #StephenCleary pattern of async initialization.
The difference being the caller doesn't need to 'remember' to await the InitializationTask, or even know anything about the initializationTask (in fact it is now changed to private).
The way it works is that in every method that uses the initialized data there is an initial call to await _initializationTask. This returns instantly the second time around - because the _initializationTask object itself will have a boolean set (IsCompleted which the 'await' mechanism checks) - so don't worry about it initializing multiple times.
The only catch I'm aware of is you mustn't forget to call it in every method that uses the data.
public sealed class MyType
{
public MyType()
{
_initializationTask = InitializeAsync();
}
private Task _initializationTask;
private async Task InitializeAsync()
{
// Asynchronously initialize this instance.
_customers = await LoadCustomersAsync();
}
public async Task<Customer> LookupCustomer(string name)
{
// Waits to ensure the class has been initialized properly
// The task will only ever run once, triggered initially by the constructor
// If the task failed this will raise an exception
// Note: there are no () since this is not a method call
await _initializationTask;
return _customers[name];
}
// one way of clearing the cache
public void ClearCache()
{
InitializeAsync();
}
// another approach to clearing the cache, will wait until complete
// I don't really see a benefit to this method since any call using the
// data (like LookupCustomer) will await the initialization anyway
public async Task ClearCache2()
{
await InitializeAsync();
}
}
You could use my AsyncContainer IoC container which supports the exact same scenario as you.
It also supports other handy scenarios such as async initializers, run-time conditional factories, depend on async and sync factory functions
//The email service factory is an async method
public static async Task<EmailService> EmailServiceFactory()
{
await Task.Delay(1000);
return new EmailService();
}
class Service
{
//Constructor dependencies will be solved asynchronously:
public Service(IEmailService email)
{
}
}
var container = new Container();
//Register an async factory:
container.Register<IEmailService>(EmailServiceFactory);
//Asynchronous GetInstance:
var service = await container.GetInstanceAsync<Service>();
//Safe synchronous, will fail if the solving path is not fully synchronous:
var service = container.GetInstance<Service>();
I know this is an old question, but it's the first which appears on Google and, quite frankly, the accepted answer is a poor answer. You should never force a delay just so you can use the await operator.
A better approach to an initialization method:
private async Task<bool> InitializeAsync()
{
try{
// Initialize this instance.
}
catch{
// Handle issues
return await Task.FromResult(false);
}
return await Task.FromResult(true);
}
This will use the async framework to initialize your object, but then it will return a boolean value.
Why is this a better approach? First off, you're not forcing a delay in your code which IMHO totally defeats the purpose of using the async framework. Second, it's a good rule of thumb to return something from an async method. This way, you know if your async method actually worked/did what it was supposed to. Returning just Task is the equivalent of returning void on a non-async method.
I have a variation of Stephen Cleary's example of an asynchronous initialization pattern. You could encapsulate the Initialization property and await it in the class methods. In this case, the client code will not need to await the initialization task.
public class ClassWithAsyncInit
{
public ClassWithAsyncInit()
{
Initialization = InitializeAsync();
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
// your async init code
}
public async Task FirstMethod()
{
await Initialization;
// ... other code
}
}
The drawback is that it's not convenient if you have a lot of methods in your class and need to await the Initialization task in each one. But sometimes it is okay. Let's say you have a simple interface for saving some JSON objects:
public IDataSaver
{
void Save(string json);
}
And you need to implement it for a database with the asynchronous initialization logic. Considering that you would have only one public method it makes sense to encapsulate the Initialization property and await it in the Save method:
public class SomeDbDataSaver: IDataSaver
{
protected DatabaseClient DbClient { get; set; }
public SomeDbDataSaver()
{
DbClient = new DatabaseClient();
Initialization = InitializeAsync(); // start off the async init
}
private Task Initialization { get; private set; }
private async Task InitializeAsync()
{
await DbClient.CreateDatabaseIfNotExistsAsync("DatabaseName");
}
public async Task Save(string json)
{
await Initialization;
// ... code for saving a data item to the database
}
}

Categories

Resources