How to limit the execution time of a function in c sharp? - c#

I've got a problem. I'm writing a benchmark and I have a function than is either done in 2 seconds or after ~5 minutes(depending on the input data). And I would like to stop that function if it's executed for more than 3 seconds...
How can I do it?
Thanks a lot!

Well..., I had the same question, and after reading all the answers here and the referred blogs, I settled for this,
It Lets me execute any block of code with a time limit, Declare the wrapper method
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
And use that to wrap any block of code like this
// code here
bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000), () =>
{
//
// Write your time bounded code here
//
});
//More code

The best way would be that your function can check its execution time often enough to decide to stop it it takes too long.
If this is not the case, then run the function in a separate thread. In your main thread start a 3 seconds timer. When timer elapses, kill the separate thread using Thread.Abort() (of course unless the function is already over). See sample code and preacuations of usage in the function docs.

The best way in C# to stop function in middle is the return keyword in function, but how do I know when to use the return keyword to stop the function in middle, after it lasts at least 3 seconds? The Stopwatch class from System.Diagnostics is the answer. This complicated function that lasts between 2 seconds to 5 minutes (depending on the input data) logically uses many loops, and maybe even recursion, so my solution for you is that, at the first line code of that function, create an instance of Stopwatch using System.Diagnostics with the new keyword, start it by calling the Start() function of the Stopwatch class, and in for each loop and loop, at the beginning, add the following code:
if (stopwatch.ElapsedMilliseconds >= 3000) {
stopwatch.Stop();
// or
stopwatch.Reset();
return;
}
(tip: you can type it with hands once, copy it Ctrl+C, and then just paste it Ctrl+V). If that function uses recursion, in order to save memory, make the Stopwatch global instance rather than creating it as local instance at first, and start it if it does not running at the beginning of the code. You can know that with the IsRunning of the Stopwatch class. After that ask if elapsed time is more than 3 seconds, and if yes (true) stop or reset the Stopwatch, and use the return keyword to stop the recursion loop, very good start in function, if your function lasts long time due mainly recursion more than loops. That it is. As you can see, it is very simple, and I tested this solution, and the results showed that it works! Try it yourself!

private static int LongRunningMethod()
{
var r = new Random();
var randomNumber = r.Next(1, 10);
var delayInMilliseconds = randomNumber * 1000;
Task.Delay(delayInMilliseconds).Wait();
return randomNumber;
}
And
var task = Task.Run(() =>
{
return LongRunningMethod();
});
bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));
if (isCompletedSuccessfully)
{
return task.Result;
}
else
{
throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}
it work for me!
Source: https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-a-c-function-to-run-for/

You can use the fork/join pattern, in the Task Parallel Library this is implemented with Task.WaitAll()
using System.Threading.Tasks;
void CutoffAfterThreeSeconds() {
// start function on seperate thread
CancellationTokenSource cts = new CancellationTokenSource();
Task loop = Task.Factory.StartNew(() => Loop(cts.Token));
// wait for max 3 seconds
if(Task.WaitAll(new Task[]{loop}, 3000)){
// Loop finished withion 3 seconds
} else {
// it did not finish within 3 seconds
cts.Cancel();
}
}
// this one takes forever
void Loop() {
while (!ct.IsCancellationRequested) {
// your loop goes here
}
Console.WriteLine("Got Cancelled");
}
This will start the other task on a seperate thread, and then wait for 3000 milliseconds for it to finish. If it did finish within the timeout, it return true, else false so you can use that to decide what to do next.
You can use a CancellationToken to communicate to the other thread that it result is no longer needed so it can stop gracefully.
Regards Gert-Jan

Run this function in thread and kill it after 3 seconds or check elapsed time inside this function(I think it's loop there).

Use an OS callbacks with a hi performance counter, then kill your thread, if exists

It is possible to execute a function in a separate thread and limit its execution with Thread.Join(millisecondsTimeout):
using System.Threading;
Thread workThread = new Thread(DoFunc);
workThread.Start(param);
if (!workThread.Join(3000))
{
// DoFunc() took longer than 3 seconds. Thread was aborted
}
private void DoFunc(object param)
{
// do some long work
}

Since C# and .net framework are not real-time environments, you can't guarantee even the 3 seconds count. Even if you were to get close to that, you would still have to call the
if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier; before every other call in the method.
All this is just wrong so no, there is just no reliable way to do it from what I know.
Although you can try this solution
https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time
but I just wouldn't do such things in .net application.

Related

Parallel.ForEach blocked on long iteration

I've been using Parallel.ForEach to do some time-consuming processing on collections of items. The processing is actually handled by an external command line tool and I cannot change that. However, it seems that the Parallel.ForEach will get "stuck" on a long running item from the collection. I've distilled the problem down and can show that Parallel.ForEach is, in fact, waiting for this long one to finish and not allowing any others through. I've written a console app to demonstrate the problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testParallel
{
class Program
{
static int inloop = 0;
static int completed = 0;
static void Main(string[] args)
{
// initialize an array integers to hold the wait duration (in milliseconds)
var items = Enumerable.Repeat(10, 1000).ToArray();
// set one of the items to 10 seconds
items[50] = 10000;
// Initialize our line for reporting status
Console.Write(0.ToString("000") + " Threads, " + 0.ToString("000") + " completed");
// Start the loop in a task (to avoid SO answers having to do with the Parallel.ForEach call, itself, not being parallel)
var t = Task.Factory.StartNew(() => Process(items));
// Wait for the operations to compelte
t.Wait();
// Report finished
Console.WriteLine("\nDone!");
}
static void Process(int[] items)
{
// SpinWait (not sleep or yield or anything) for the specified duration
Parallel.ForEach(items, (msToWait) =>
{
// increment the counter for how many threads are in the loop right now
System.Threading.Interlocked.Increment(ref inloop);
// determine at what time we shoule stop spinning
var e = DateTime.Now + new TimeSpan(0, 0, 0, 0, msToWait);
// spin until the target time
while (DateTime.Now < e) /* no body -- just a hard loop */;
// count another completed
System.Threading.Interlocked.Increment(ref completed);
// we're done with this iteration
System.Threading.Interlocked.Decrement(ref inloop);
// report status
Console.Write("\r" + inloop.ToString("000") + " Threads, " + completed.ToString("000") + " completed");
});
}
}
}
Basically, I make an array of int to store the number of milliseconds a given operation takes. I set them all to 10 except for one, which I set to 10000 (so, 10 seconds). I kick off the Parallel.ForEach in a task and process each integer in a hard spin wait (so it shouldn't be yielding or sleeping or anything).
On each iteration, I report how many iterations are in the body of the loop right now, and how many iterations we have completed. Mostly, it goes along fine. However, toward the end (time-wise), it reports "001 Threads, 987 Completed".
My question is why doesn't it use 7 of the other cores to work on the remaining 13 "jobs"? This one long-running iteration should not keep it from processing other elements in the collection, right?
This example happens to be a fixed collection, but it could easily be set to be an enumerable. We wouldn't want to stop fetching the next item in the enumerable just because one was taking a long time.
I found the answer (or at least, an answer). It has to do with the chunk partitioning. The SO answer here got it for me. So basically, at the top of my "Process" function, if I change from this:
static void Process(int[] items)
{
Parallel.ForEach(items, (msToWait) => { ... });
}
to this
static void Process(int[] items)
{
var partitioner = Partitioner.Create(items, EnumerablePartitionerOptions.NoBuffering);
Parallel.ForEach(partitioner, (msToWait) => { ... });
}
it grabs the work one at a time. For the more typical case of a parallel for each, where the body doesn't take more than a second, I can certainly see chunking the sets of work. In my use case, however, each body part can take anywhere from half a second to 5 hours. I certainly would not want a bunch of the 10-second variety elements to be blocked by one 5 hour element. So, in this case, the overhead of "one-at-a-time" is well worth it.

Call Join for multiple threads simultaneously

I am writing a script in C# for Unity to read messages from multiple sources. I have a function ReadMessage which takes in a port string and returns a string ID number. The issue is, I have a dozen different connections I need to read from and the messages have a 10ms timeout timer before it stops trying and lets the code continue. This causes a reduction in frame rate when I have a dozen threads waiting a few ms for the previous one to finish Joining. My thread code is as follows:
string threadOneString= null;
Thread ThreadOne;
//Repeat for 11 more threads
void Update () {
ThreadOne = new Thread(
() =>
{
threadOneString = ReadMessage(someClass.port);
});
ThreadOne.Start();
//Repeat for 11 more threads
}
void LateUpdate () {
ThreadOne.Join();
//Repeat for 11 more threads
UpdateClass(threadOneString);
//Repeat for 11 more threads
UpdateTextDisplay(); //Just updates a Unity Text object
}
And my ReadMessage code in case it matters.
private string ReadMessage(string port) //Change this name to ReadButtonPress
{
string fullMessage = "";
someStruct parsedMessage;
var timeout = new System.TimeSpan(0, 0, 0, 0, 10); // Less than 10 and it starts to miss most messages, ideally this would be a bit higher
string connectionString = PROTOCOL + CONTROLLER_IP + ":" + port;
AsyncIO.ForceDotNet.Force();
using (var subSocket = new SubscriberSocket())
{
subSocket.Connect(connectionString);
subSocket.Subscribe("");
subSocket.TryReceiveFrameString(timeout, out fullMessage);
UnityEngine.Debug.Log("Message: " + fullMessage);
subSocket.Close();
}
// Some message parsing and checking...
return parsedMessage.someString;
}
What I'd like to do, but I don't know if it's possible, is to call the Joins for each thread at the same time instead of calling one, waiting, then calling the next. The threads don't interact with each other, so I'm hoping this is possible. If not, I'd greatly appreciate another solution or suggestion.
EDIT: Clarification on what's happening. When I only run a few threads I get a FPS of 65-70. When I run all 12 threads my FPS drops to ~50 and I have a hard requirement of 60 FPS.
Thanks to some feedback here I am no longer creating a socket every update. Instead I create the sockets in Start() and just read what I need from a public function in the class. I based my code on https://stackoverflow.com/a/14797475/8635796
Don't do what I did and recreate the exact same threads and sockets every Update(). In hindsight, it was a really poor choice.
Use tasks instead, and put them into a list.
var myTasks = new List<Task>();
Task allUpdateTasks;
...
void Update () {
myTasks.Add(
Task.Factory.StartNew(() =>
{
threadOneString = ReadMessage(someClass.port);
}));
//Repeat for 11 more tasks
// Create a single tasks that will hold all tasks above.
allUpdateTasks = Task.WhenAll(myTasks);
}
void LateUpdate() {
allUpdateTasks.Wait();
...
}
define ManualResetEvent and signal it when you got results, you can wait up to 64 waithandles using WaitHandle.WaitAny

Cancel execution of command if it takes too long

I am currently working on a piece of software that uses an assembly from a different department.I call a Method from this assembly like this:
using (var connection = (IConnection) Factory.GetObject(typeof (IConnection)))
The code used to work perfectly fine. But for the last few minutes it seemed like my program was doing nothing when I tried to launch it. Pressing pause while debugging showed me it got "stuck" at the line above.My guess is they're just doing some maintenance or something but that's not the point here.
So I though it would be nice to tell the user what went wrong if the program doesn't start. Something simple like
MessageBox.Show("Could not connect", "Connection Error");
And then close the program. My question is:
How do I terminate the execution of a command after a set amount of time and jump somewhere else?My guess would be moving it to a separate thread and then putting the calling thread to sleep for a few seconds after which it disposes of the extra thread if it isn't completed yet. But that seems really dirty to me and there's got to be a better way.
Your question can be separated into two parts:
How to terminate the execution of a command?
The only way is to abort the thread. But don't do it. There is no guaranteed and safe way. There are such methods like Thread.Interrupt and Thread.Abort that can wake up the thread. But they will work only if the thread is in the WaitSleepJoin state and it hangs in managed code.
Seems like you already know it. But once again, if something inside the assembly hangs infinitely the execution of code then the thread is probably "gone". So you are right that the program should be closed.
... jump somewhere else?
Good approach is using of TPL and async model.
Here is an extension method to wrap up any Task and expires after timeout.
public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
{
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
await task;
else
throw new TimeoutException();
}
Then use it
try
{
using (var result = await Task.Run(() => (IConnection)Factory.GetObject(typeof(IConnection))).TimeoutAfter(1000))
{
...
}
}
catch (TimeoutException ex)
{
//timeout
}
Here you can find more information
A simple way of doing it without extra libraries or extension methods:
using ( var task = new Task<IConnection>( () => Factory.GetObject( typeof( IConnection ) ) ) )
{
task.Start();
if( !task.Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
IConnection result = task.Result;
}
Task.Wait does what you want, because you can throw an exception if it returns false (task didn't complete in time.)
It's even simpler if you have an Action that doesn't return something:
if ( !Task.Run( action ).Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
Where action is some Action or lambda.
The easiest way to do this, if a native timeout is not implemented, as you mentioned, is a separate thread to load it on. Although this sounds like it'll be really dirty, it's as simple as (using Rx):
Task<IConnection> connectionTask = Observable.Start(() => Factory.GetObject(typeof (IConnection)), Scheduler.Default).Timeout(TimeSpan.FromSeconds(20)).ToTask());
using (var connection = connectionTask.Result)
{
...
}
You can tweak the Scheduler if you don't want it to run on the threadpool. It will throw a TimeoutException if the Factory.GetObject call takes longer than 20 seconds.
You could use CancellationTokenSource to set a timeout on the operation
var timeoutCts = new CancellationTokenSource();
try
{
timeoutCts.CancelAfter(300000); // Cancel after 5 minutes
// ... run your long term operation
}
catch (OperationCanceledException ex)
{
// Handle the timeout
}
Please see this documentation from Microsoft
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Run(() =>
{
Random rnd = new Random();
long sum = 0;
int n = 5000000;
for (int ctr = 1; ctr <= n; ctr++)
{
int number = rnd.Next(0, 101);
sum += number;
}
Console.WriteLine("Total: {0:N0}", sum);
Console.WriteLine("Mean: {0:N2}", sum / n);
Console.WriteLine("N: {0:N0}", n);
});
TimeSpan ts = TimeSpan.FromMilliseconds(150);
if (!t.Wait(ts))
Console.WriteLine("The timeout interval elapsed.");
}
}

await Task.Delay(foo); takes seconds instead of ms

Using a variable delay in Task.Delay randomly takes seconds instead of milliseconds when combined with a IO-like operation.
Code to reproduce:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication {
class Program {
static void Main(string[] args) {
Task[] wait = {
new delayTest().looper(5250, 20),
new delayTest().looper(3500, 30),
new delayTest().looper(2625, 40),
new delayTest().looper(2100, 50)
};
Task.WaitAll(wait);
Console.WriteLine("All Done");
Console.ReadLine();
}
}
class delayTest {
private Stopwatch sw = new Stopwatch();
public delayTest() {
sw.Start();
}
public async Task looper(int count, int delay) {
var start = sw.Elapsed;
Console.WriteLine("Start ({0}, {1})", count, delay);
for (int i = 0; i < count; i++) {
var before = sw.Elapsed;
var totalDelay = TimeSpan.FromMilliseconds(i * delay) + start;
double wait = (totalDelay - sw.Elapsed).TotalMilliseconds;
if (wait > 0) {
await Task.Delay((int)wait);
SpinWait.SpinUntil(() => false, 1);
}
var finalDelay = (sw.Elapsed - before).TotalMilliseconds;
if (finalDelay > 30 + delay) {
Console.WriteLine("Slow ({0}, {1}): {4} Expected {2:0.0}ms got {3:0.0}ms", count, delay, wait, finalDelay, i);
}
}
Console.WriteLine("Done ({0}, {1})", count, delay);
}
}
}
Also reported this on connect.
Leaving old question bellow, for completeness.
I am running a task that reads from a network stream, then delays for 20ms, and reads again (doing 500 reads, this should take around 10 seconds). This works well when I only read with 1 task, but strange things happen when I have multiple tasks running, some with long (60 seconds) delay. My ms-delay tasks suddenly hang half way.
I am running the following code (simplified):
var sw = Stopwatch();
sw.Start()
await Task.Delay(20); // actually delay is 10, 20, 30 or 40;
if (sw.Elapsed.TotalSeconds > 1) {
Console.WriteLine("Sleep: {0:0.00}s", sw.Elapsed.TotalSeconds);
}
This prints:
Sleep: 11.87s
(Actually it gives the 20ms delay 99% of the time, those are ignored).
This delay is almost 600 times longer than expected. The same delay happens on 3 separate threads at the same time, and they all continue again at the same time also.
The 60 second sleeping task wakes up as normal ~40 seconds after the short tasks finish.
Half the time this problem does not even happen. The other half, it has a consistent delay of 11.5-12 seconds. I would suspect a scheduling or thread-pool problem, but all threads should be free.
When I pause my program during the stuck phase, the main thread stacktrace stands on Task.WaitAll, 3 tasks are Scheduled on await Task.Delay(20) and one task is Scheduled on await Task.Delay(60000). Also there are 4 more tasks Awaiting those first 4 tasks, reporting things like '"Task 24" is waiting on this object: "Task 5313" (Owned by thread 0)'. All 4 tasks say the waiting task is owned by thread 0. There are also 4 ContinueWith tasks that I think I can ignore.
There are some other things going on, like a second console application that writes to the network stream, but one console application should not affect the other.
I am completely clueless on this one. What is going on?
Update:
Based on comments and questions:
When I run my program 4 times, 2-3 times it will hang for 10-15 seconds, 1-2 times it will operate as normal (and wont print "Sleep: {0:0.00}s".)
Thread.Count indeed goes up, but this happens regardless of the hang. I just had a run where it did not hang, and Thread.Count started at 24, wend up to 40 after 1 second, around 22 seconds the short tasks finished normal, and then Thread.Count wend down to 22 slowly over the next 40 seconds.
Some more code, full code is found in the link below. Starting clients:
List<Task> tasks = new List<Task>();
private void makeClient(int delay, int startDelay) {
Task task = new ClientConnection(this, delay, startDelay).connectAsync();
task.ContinueWith(_ => {
lock (tasks) { tasks.Remove(task); }
});
lock (tasks) { tasks.Add(task); }
}
private void start() {
DateTime start = DateTime.Now;
Console.WriteLine("Starting clients...");
int[] iList = new[] {
0,1,1,2,
10, 20, 30, 40};
foreach (int delay in iList) {
makeClient(delay, 0); ;
}
makeClient(15, 40);
Console.WriteLine("Done making");
tasks.Add(displayThreads());
waitForTasks(tasks);
Console.WriteLine("All done.");
}
private static void waitForTasks(List<Task> tasks) {
Task[] waitFor;
lock (tasks) {
waitFor = tasks.ToArray();
}
Task.WaitAll(waitFor);
}
Also, I tried to replace the Delay(20) with await Task.Run(() => Thread.Sleep(20))
Thread.Count now goes from 29 to 43 and back down to 24, however among multiple runes it never hangs.
With or without ThreadPool.SetMinThreads(500, 500), using TaskExt.Delay by noserati it does not hang. (That said, even switching over 1 line of code sometimes stops it from hanging, only to randomly continue after I restart the project 4 times, but I've tried this 6 times in a row without any problems now).
I've tried everything above with and without ThreadPool.SetMinThreads so far, never made any difference.
Update2: CODE!
Without seeing more code, it's hard to make futher guesses, but I'd like to summarize the comments, it may help someone else in the future:
We've figured out that the ThreadPool stuttering is not an issues here, as ThreadPool.SetMinThreads(500, 500) didn't help.
Is there any SynchronizationContext in place anywhere in your task workflow? Place Debug.Assert(SyncrhonizationContext.Current == null) everywhere to check for that. Use ConfigureAwait(false) with every await.
Is there any .Wait, .WaitOne, .WaitAll, WaitAny, .Result used anywhere in your code? Any lock () { ... } constructs? Monitor.Enter/Exit or any other blocking synchronization primitives?
Regarding this: I've already replaced Task.Delay(20) with Task.Yield(); Thread.Sleep(20) as a workaround, that works. But yeah, I continue to try to figure out what's going on here because the idea that Task.Delay(20) can shoot this far out of line makes it totally unusable.
This sounds worrying, indeed. It's very unlikely there's a bug in Task.Delay, but everything is possible. For the sake of experimenting, try replacing await Task.Delay(20) with await Task.Run(() => Thread.Sleep(20)), having ThreadPool.SetMinThreads(500, 500) still in-place.
I also have an experimental implementation of Delay which uses unamanaged CreateTimerQueueTimer API (unlike Task.Delay, which uses System.Threading.Timer, which in turn uses managed TimerQueue). It's available here as a gist. Feel free to try it as TaskExt.Delay instead of the standard Task.Delay. The timer callbacks are posted to ThreadPool, so ThreadPool.SetMinThreads(500, 500) still should be used for this experiment. I doubt it could make any difference, but I'd be interested to know.

Multithreading in WCF with accurate timer requirement

I have a WCF app that accepts requests to start a job. Each job needs to do something after exactly X minutes (e.g. 5 mins.), there can also be a job request at any time and simultaneously.
This is what I have in mind,
// WCF class
public class RequestManager
{
// WCF method
public void StartNewJob()
{
// start a new thread with timer for each job?
}
}
public class Job
{
public Job()
{
// do some initializations
// do something after x mins
// sleep or timer?
}
private void DoSomething()
{
// do some follow-ups
}
}
With my approach, I'm afraid that there will be too many threads that's doing nothing for X mins. Per-second accuracy would be a requirement as well (say it starts a job at 0:05:01, the follow up should be at 0:10:01).
What would be the best way to approach this?
I would suggest you looking at the RegisterWaitForSingleObject function:
var waitObject = new AutoResetEvent(false);
// Execute the callback on a new thread 10 seconds after this call
// and execute it only once
ThreadPool.RegisterWaitForSingleObject(
waitObject,
(state, timeout) => { Console.WriteLine("ok"); },
null,
TimeSpan.FromSeconds(10),
true);
// Execute the callback on a new thread 10 seconds after this call
// and continue executing it at 10 seconds intervals until the
// waitHandle is signaled.
ThreadPool.RegisterWaitForSingleObject(
waitObject,
(state, timeout) => { Console.WriteLine("ok"); },
null,
TimeSpan.FromSeconds(10),
false);
Sounds like you need the serives of the Timer class:
// WCF class
public class RequestManager
{
// WCF method
public void StartNewJob()
{
Job myJob = new Job();
// Initialise myJob...
myJob.Start();
}
}
public class Job
{
private Timer myTimer = new Timer();
public Job()
{
myTimer.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);
}
public void Start(int Miniutes)
{
myTimer.Interval = 60000 * Miniutes;
myTimer.Enabled = true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// So something
}
}
The above code assumes that:
You dont do anything silly like attempt to call Start() twice on the same instance of timer.
There is some other non-background thread active elsewhere in the application preventing the application from closing.
Its not a full example, but hopefully it should give you the idea - the Timer class will deal with keeping time without needing a thread active for each job.
You need to use some timing/scheduling framework like Quartz.NET or create your own one (lightweight).
Using timer seems to be good (and easier to implement) for me.
There are several timer classes you can use in .NET. Please see the following document (even though it's bit aged, but it seems to be a good start): Comparing the Timer Classes in the .NET Framework Class Library
However, you can still achieve this behavior with Thread.Sleep() as well by calculating the offset while taking timestamps on a thread wake-up and on a completion of Job.DoSomethig().
You may want to consider the followings carefully:
Any contentions between threads executing Job.DoSomething()?
You should be very careful in the following scenario: what if Job.DoSomething() sometimes takes more than the period (i.e. it starts at 0:05 and completes 0:13 in the example above). What does this mean to your application and how will it be handled?
a. Total failure - abort the current(0:05) execution at 0:10 and launch 0:10 execution.
b. Not a big deal (skip 0:10 one and run Job.DoSomething() at 0:15).
c. Not a big deal, but need to launch 0:10 execution immediately after 0:05 task finishes (what if it keeps taking more than 5 sec??).
d. Need to launch 0:10 execution even though 0:05 execution is currently running.
e. anything else?
For the policy you select above, does your choice of implementation (either any of timer classes listed above or Thread.Sleep()) easy to support your policy?

Categories

Resources