C# Dispatching code to run at a later time? - c#

How can I dispatch code to run at a later time? something like :
ThreadPool.QueueUserWorkItem(callback, TimeSpan.FromSeconds(1)); // call callback() roughly one second from now

You can try the following:
System.Threading.Timer _timeoutTimer;
//...
int timeout = (int)TimeSpan.FromSeconds(1).TotalMilliseconds;
_timeoutTimer = new System.Threading.Timer(OnTimerElapsed,
null, timeout, System.Threading.Timeout.Infinite);
//...
void OnTimerElapsed(object state) {
// do something
_timeoutTimer.Dispose();
}

You can use the Timer class for this.

Just put a sleep in your callback function. If you are using Threadpool or Task it may take longer than the actual timespan you send before getting started; this is because the thread won't start executing immediately if it's queued.
public static void MyCallback(object delay)
{
Thread.Sleep(((TimeSpan)delay).TotalMilliseconds);
... code ...
}
You could do the above inline with an anonymous method and using the lower level thread construct.
new Thread(() => {
Thread.Sleep(delayMilliseconds);
callbackFunction();
}).Start();

Related

Should Timer be waiting for callback to finish before firing a new one?

I am using the System.Threading.Timer class in one of my projects and I've noticed that the callback methods are called before the previous ones get to finish which is different than what I was expecting.
For example the following code
var delta = new TimeSpan(0,0,1);
var timer = new Timer(TestClass.MethodAsync, null, TimeSpan.Zero, delta);
static class TestClass
{
static int i = 0;
public static async void MethodAsync(object _)
{
i++;
Console.WriteLine("method " + i + "started");
await Task.Delay(10000);
Console.WriteLine("method " + i + "finished");
}
}
has this output
method 1started
method 2started
method 3started
method 4started
method 5started
method 6started
method 7started
method 8started
method 9started
method 10started
method 11started
method 11finished
method 12started
method 12finished
Which of course is not thread safe. What I was expecting is that a new call would be made to the callback method after the previous call has succeeded and additionally after the delta period is elapsed.
What I am looking for is where in the docs from Microsoft is this behavior documented and maybe if there is a built in way to make it wait for the callback calls to finish before starting new ones
The problem of overlapping event handlers is inherent with the classic multithreaded .NET timers (the System.Threading.Timer and the System.Timers.Timer). Attempting to solve this problem while remaining on the event-publisher-subscriber model is difficult, tricky, and error prone. The .NET 6 introduced a new timer, the PeriodicTimer, that attempts to solve this problem once and for all. Instead of handling an event, you start an asynchronous loop and await the PeriodicTimer.WaitForNextTickAsync method on each iteration. Example:
class TestClass : IDisposable
{
private int i = 0;
private PeriodicTimer _timer;
public async Task StartAsynchronousLoop()
{
if (_timer != null) throw new InvalidOperationException();
_timer = new(TimeSpan.FromSeconds(1));
while (await _timer.WaitForNextTickAsync())
{
i++;
Console.WriteLine($"Iteration {i} started");
await Task.Delay(10000); // Simulate an I/O-bound operation
Console.WriteLine($"Iteration {i} finished");
}
}
public void Dispose() => _timer?.Dispose();
}
This way there is no possibility for overlapping executions, provided that you will start only one asynchronous loop.
The await _timer.WaitForNextTickAsync() returns false when the timer is disposed. You can also stop the loop be passing a CancellationToken as argument. When the token is canceled, the WaitForNextTickAsync will complete with an OperationCanceledException.
In case the periodic action is not asynchronous, you can offload it to the ThreadPool, by wrapping it in Task.Run:
await Task.Run(() => Thread.Sleep(10000)); // Simulate a blocking operation
If you are targeting a .NET platform older than .NET 6, you can find alternatives to the PeriodicTimer here.
What I am looking for is where in the docs from Microsoft is this behavior documented...
System.Threading.Timer
If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
System.Timers.Timer
The callback method executed by the timer should be reentrant, because it is called on ThreadPool threads.
For System.Windows.Forms.Timer this post asserts that the event does wait. The documentation doesn't seem very specific, but in the Microsoft Timer.Tick Event official example the code shows turning the timer off and on in the handler. So it seems that, regardless, steps are taken to prevent ticks and avoid reentrancy.
...and if there is a built in way to make it wait for the callback calls to finish before starting new ones.
According to the first Microsoft link (you might consider this a workaround, but it's straight from the horse's mouth):
One way to resolve this race condition is to set a flag that tells the event handler for the Elapsed event to ignore subsequent events.
The way I personally go about achieving this objective this is to call Wait(0) on the synchronization object of choice as a robust way to ignore reentrancy without having timer events piling up in a queue:
static SemaphoreSlim _sslim = new SemaphoreSlim(1, 1);
public static async void MethodAsync(object _)
{
if (_sslim.Wait(0))
{
try
{
i++;
Console.WriteLine($"method {i} started # {DateTime.Now}");
await Task.Delay(10000);
Console.WriteLine($"method {i} finished # {DateTime.Now}");
}
catch (Exception ex)
{
Debug.Assert(false, ex.Message);
}
finally
{
_sslim.Release();
}
}
}
In which case your MethodAsync generates this output:

Aborting a stuck method after a timeout

Our program is executing unknown methods from a DLL. Sometimes those methods won't handle timeouts and will never return a value.
Thus, our Methodinfo.invoke(...) will be stuck on this line forever.
Is there any decent way to abort our method?
I understand that i should probably run this method asyncronious which is no problem.
as requested here is some little example for visualisation:
public string startTheDLLMethod(int timeout)
{
var methodinfo = "...";
return methodGettingStuck(methodinfo); //todo, abort this after timeout
}
public string methodGettingStuck(methodinfo)
{
var1 = "";
var2 = "";
methodinfo.Invoke(var1, var2); //Stuck.
}
As suggested in the comment i would try to not work with ThreadAbortException if something like a file handle is allocated within the dll.
But here you go:
public void BlockingCallWithTimeout()
{
Semaphore waitHandle = new Semaphore(0,1);
Thread thread = new Thread(this.Wrapper);
Timer timer = new Timer(state =>
{
thread.Abort();
waitHandle.Release();
},null,5000,0);
thread.Start(waitHandle);
waitHandle.WaitOne(); //wait until completion or until timeout
timer.Dispose();
}
public void Wrapper(object state)
{
Semaphore semaphore = (Semaphore)state;
//Call DLL Method
semaphore.Release();
}
You need to handle the ThreadAbortException somewhere in the code (did not try it). This code is just an example! you need to take care of the case where timeout and success occur at the same time. So the Timer is not disposed the moment it is executing - and there may be more race conditions to take care of.

Running task in loop

I have a function which can take 5-60 seconds to run, and I need to run it for every 10 seconds but it should be started only when the previously started function finished running, my code for now is
Action myAction = new Action(() =>
{
Debug.WriteLine("just testing");
Thread.Sleep(15000);
});
Task myTask = Task.Factory.StartNew(myAction, _cts.Token);
Timer myTimer = new Timer(state =>
{
if (myTask.IsCompleted)
{
myTask = Task.Factory.StartNew(myAction, _cts.Token);
}
}, null, 10000, 10000);
Everything is working fine but I wonder if there is a better solution for my problem? Or is there a possibility to not create a new task (Task.Factory.StartNew) but just using the one used by myTimer?
You can use ContinueWith():
Task.Factory.StartNew(myAction, _cts.Token).ContinueWith(_ => myAction);
Look for it's overloads, it has many options to control on which cases to run the continuation.
There is a great open source task scheduler called Quartz.net. You can find it at http://quartznet.sourceforge.net/
It supports the specific scenario you mentioned. It is a very robust solution with good extensibility.
Another possibility, if you are adventurous, would be to use Rx:
Observable.Timer(TimeSpan.FromSeconds(10)).TakeUntilCanceled(cancel).Subscribe(_ => myAction);
Using the TakeUntilCanceled extension:
public static class CancellationTokenXs
{
public static IObservable<T>
TakeUntilCanceled<T>(this IObservable<T> source, CancellationToken cancellationToken)
{
var subject = new Subject<Unit>();
cancellationToken.Register(() => subject.OnNext(new Unit()), true);
return source.TakeUntil(subject);
}
}
A much better idea would be to, instead of trying to call it every 10 seconds, rely on a callback on task completion, as an example in the following code:
DateTime sinceExec = DateTime.Now;
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += (bgSender, bgArgs) =>
{
sinceExec = DateTime.Now;
Debug.WriteLine("Test!");
Thread.Sleep(5000);
};
bgWorker.RunWorkerCompleted += (bgSender, bgArgs) =>
{
// it didn't take 10000 milliseconds
if ((DateTime.Now - sinceExec).Milliseconds < 10000)
{
//Calculate time to wait
TimeSpan timeToWait = (DateTime.Now - sinceExec);
// wait that amount of time
Thread.Sleep(timeToWait);
}
//Re-execute the worker
bgWorker.RunWorkerAsync();
};
bgWorker.RunWorkerAsync();
The BackgroundWorker class functions such that the event handler DoWork is executed when RunWorkerAsync() is called and RunWorkerCompleted is invoked when DoWork completes.
You can use a lock statement. A lock statement creates a critical section, only one of which can be run at once for a given object.
Use an object both your main thread and your task thread can have access to as the mutex lock. Surrounding both the task function's code and the line that starts the task with the lock statement will accomplish your goal. The task function will acquire the lock and will not release it until it has finished, and the creation function will wait to acquire the lock before it creates another task.
Action myAction = new Action(() =>
{
lock(this)
{
Debug.WriteLine("just testing");
Thread.Sleep(15000);
}
});
And in your code that kicks off the action,
lock(myAction)
{
Task.Factory.StartNew(myAction, _cts.Token)
}

Waiting for an async method to end in C#

Sample code:
class Program
{
static readonly object locker = new object();
static void Main(string[] args)
{
Func();
Func();
Thread.Sleep(6000);
}
static void Func()
{
Monitor.Enter(locker);
Action act = () =>
{
Thread.Sleep(2000);
};
act.BeginInvoke(a =>
{
Console.WriteLine("exiting..");
Monitor.Exit(locker);
}, null);
Console.WriteLine("Func done...");
}
}
Ideally the console would print out:
Func done...
exiting...
Func done...
exitting...
But, I'm getting:
Func done...
Func done...
exitting...
and then Monitor.Exit throws the exception
Object synchronization method was called from an unsynchronized block of code.
What is the error here? What's the preferred way to achieve this?
Monitor.Enter and Monitor.Exit calls have to be made on the same thread. In your sample you call Monitor.Enter on the UI thread and Monitor.Exit on a thread created for the asynchronous invocation triggered by BeginInvoke.
If you want to wait for the async operation to be finished within Func you could do it like this:
class Program
{
static void Main(string[] args)
{
Func();
Func();
Thread.Sleep(6000);
}
static void Func()
{
Action act = () =>
{
Thread.Sleep(2000);
};
IAsyncResult actAsyncResult = act.BeginInvoke(a =>
{
Console.WriteLine("exiting..");
}, null);
Console.WriteLine("Func done...");
act.EndInvoke(actAsyncResult);
}
}
Nevertheless in your scenario you could then just invoke the delegate synchronously.
Monitor.Enter(locker) is on the current thread, Monitor.Exit is on a different thread as it is invoked from your current thread.
Thus you need to use Monitor.Wait and Monitor.Pulse as well, but ManualResetEvents are easier in your case.
I think you can wait for an event to complete by using ManualResetEvent class. Sorry I don't have any experience with Monitor. But I am using the ManualResetEvent / AutoResetEvent classes for testing callbacks.
Thread shudn't close Monitor
Monitor.Exit(locker);
this is a problem
This error is very misleading. It really doesn't mean what it looks like it means. It actually means that Monitor.Exit is called before you called Monitor.Enter on a sync object.
Your Monitor.Exit call happens on a different thread from the Monitor.Enter call -- the two don't see each other's sync objects.

Best way to call a single operation at some time in the future?

I want to fire off a timer to execute once at some point in the future. I want to use a lambda expression for code brevity. So I want to do something like...
(new System.Threading.Timer(() => { DoSomething(); },
null, // no state required
TimeSpan.FromSeconds(x), // Do it in x seconds
TimeSpan.FromMilliseconds(-1)); // don't repeat
I think it's pretty tidy. But in this case, the Timer object is not disposed. What is the best way to fix this? Or, should I be doing a totally different approach here?
That approach is flawed.
You are creating an object in memory with no reference to it. This means that the timer object is available to be garbage collected. While this code will work some of the time, you cannot predict when a garbage collection will kick in and remove the timer.
For example in the code below I force a garbage collection and it causes the timer to never fire.
static void Main(string[] args)
{
DoThing();
GC.Collect();
Thread.Sleep(5000);
}
static void DoThing()
{
new System.Threading.Timer(x => { Console.WriteLine("Here"); },
null,
TimeSpan.FromSeconds(1),
TimeSpan.FromMilliseconds(-1));
}
This will accomplish what you want, but I am not sure its the best solution. I think its something that short and elegant, but might be more confusing and difficult to follow than its worth.
System.Threading.Timer timer = null;
timer = new System.Threading.Timer(
(object state) => { DoSomething(); timer.Dispose(); }
, null // no state required
,TimeSpan.FromSeconds(x) // Do it in x seconds
,TimeSpan.FromMilliseconds(-1)); // don't repeat
Instead of using a timer, leverage the thread pool instead:
bool fired = false;
ThreadPool.RegisterWaitForSingleObject(new ManualResetEvent(false),
(state, triggered) =>
{
fired = true;
},
0, 9000, true);
GC.Collect();
Thread.Sleep(10000);
Assert.IsTrue(fired);
This survives garbage collection since you don't have to retain a reference to anything.
You could just wrap the timer class...
class Program
{
static void Main(string[] args)
{
MyTimer.Create(
() => { Console.WriteLine("hello"); },
5000);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.Read();
}
}
public class MyTimer
{
private MyTimer() { }
private Timer _timer;
private ManualResetEvent _mre;
public static void Create(Action action, int dueTime)
{
var timer = new MyTimer();
timer._mre = new ManualResetEvent(false);
timer._timer = new Timer(
(x) =>
{
action();
timer._mre.Set();
},
null,
dueTime,
Timeout.Infinite
);
new Thread(new ThreadStart(() =>
{
timer._mre.WaitOne();
timer._timer.Dispose();
})).Start();
}
}
The timer object probably implements a destructor.
You can easily verify this in documentation or in the reflector.
If this is true, you shouldn't worry about it. Unless this piece of code gets called many times, in which case you should strive for deterministic deallocation of timers, meaning you would hold an array of timers, for example.
If you have a Dispatcher and want to be in the UI (Dispatcher) thread, use this:
void MyNonAsyncFunction()
{
Dispatcher.InvokeAsync(async () =>
{
await Task.Delay(1000);
MessageBox.Show("Thank you for waiting");
});
}
This function is not async because you did not want to wait within your function. This approach might be useful if you wanted to schedule more than one events at different times, but perhaps you really want the approach below:
async void MyAsyncFunction()
{
// Do my other things
await Task.Delay(1000);
MessageBox.Show("Thank you for waiting");
}
Which does the same thing, but requires the await to happen at the end of your function.
Since you may not have a Dispatcher or want to use it, but still want to schedule multiple operations at different times, I would use a thread:
static void MyFunction()
{
// Do other things...
Schedule(1000, delegate
{
System.Diagnostics.Debug.WriteLine("Thanks for waiting");
});
}
static void Schedule(int delayMs, Action action)
{
#if DONT_USE_THREADPOOL
// If use of threadpool is undesired:
new System.Threading.Thread(async () =>
{
await Task.Delay(delayMs);
action();
}
).Start(); // No need to store the thread object, just fire and forget
#else
// Using the threadpool:
Task.Run(async delegate
{
await Task.Delay(delayMs);
action();
});
#endif
}
If you want to avoid async, I would recommend not using the threadpool and replacing the await Task.Delay(delayMs) call with a Thread.Sleep(delayMs) call
You could use TaskCompletionSource for example:
static Task<T> ExecuteLater<T>(int delay, Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
var timer = new System.Timers.Timer(delay) { AutoReset = false };
timer.Elapsed += delegate { timer.Dispose(); tcs.SetResult(func()); };
timer.Start();
return tcs.Task;
}
and call it like:
var result = await ExecuteLater<int>(5000, () => 50);
Or simply call:
var result = await Task.Delay(5000).ContinueWith<int>((t) => { return 50; });
System.Reactive.Linq.Observable.Interval(TimeSpan.FromSeconds(1))
.FirstAsync()
.Subscribe(_ => DoSomething()));

Categories

Resources