Method calls from threads with a specific delay - c#

I need to synchronize a method call, so that threads can call this method after a 500ms sleep. I have 10 threads that may run at the same time, so that simply introducing Thread.Sleep(500) does not help. How can I achieve this in the simplest way? What can you suggest?
_pool = new Semaphore(0, 10);
_pool.Release(10);
...
pool.WaitOne();
Thread thr = new Thread(WorkerThread);
t.Start(param);
...
public static void WorkerThread(object parameterData)
{
...
MethodToBeSynced();
...
_pool.Release();
}

If you know the number of concurrent threads (And given they start approx. the same time), you could use a Barrier with a PostPhaseAction delegate.
var barrier = new Barrier(10, (x) => Thread.Sleep(500));
The barrier waits until 10 threads are at a certain code point and once that happens, each thread will sleep for 500 ms and then continues.
If the exact number of threads is unknown, you could specify a wait timeout to not block infinite.
// Waits up until N threads are at the barrier or after the timeout has elapsed.
_barrier.SignalAndWait(500);

Use System.Threading.Timer
You can give it a callback function as well as the interval when to call this function.

Related

Effects of non-awaited Task

I have a Task which I do not await because I want it to continue its own logic in the background. Part of that logic is to delay 60 seconds and check back in to see if some minute work is to be done. The abbreviate code looks something like this:
public Dictionary<string, Task> taskQueue = new Dictionary<string, Task>();
// Entry point
public void DoMainWork(string workId, XmlDocument workInstructions){
// A work task (i.e. "workInstructions") is actually a plugin which might use its own tasks internally or any other logic it sees fit.
var workTask = Task.Factory.StartNew(() => {
// Main work code that interprets workInstructions
// .........
// .........
// etc.
}, TaskCreationOptions.LongRunning);
// Add the work task to the queue of currently running tasks
taskQueue.Add(workId, workTask);
// Delay a period of time and then see if we need to extend our timeout for doing main work code
this.QueueCheckinOnWorkTask(workId); // Note the non-awaited task
}
private async Task QueueCheckinOnWorkTask(string workId){
DateTime startTime = DateTime.Now;
// Delay 60 seconds
await Task.Delay(60 * 1000).ConfigureAwait(false);
// Find out how long Task.Delay delayed for.
TimeSpan duration = DateTime.Now - startTime; // THIS SOMETIMES DENOTES TIMES MUCH LARGER THAN EXPECTED, I.E. 80+ SECONDS VS. 60
if(!taskQueue.ContainsKey(workId)){
// Do something based on work being complete
}else{
// Work is not complete, inform outside source we're still working
QueueCheckinOnWorkTask(workId); // Note the non-awaited task
}
}
Keep in mind, this is example code just to show a extremely miniminal version of what is going on with my actual program.
My problem is that Task.Delay() is delaying for longer than the time specified. Something is blocking this from continuing in a reasonable timeframe.
Unfortunately I haven't been able to replicate the issue on my development machine and it only happens on the server every couple of days. Lastly, it seems related to the number of work tasks we have running at a time.
What would cause this to delay longer than expected? Additionally, how might one go about debugging this type of situation?
This is a follow up to my other question which did not receive an answer: await Task.Delay() delaying for longer that expected
Most often that happens because of thread pool saturation. You can clearly see its effect with this simple console application (I measure time the same way you are doing, doesn't matter in this case if we use stopwatch or not):
public class Program {
public static void Main() {
for (int j = 0; j < 10; j++)
for (int i = 1; i < 10; i++) {
TestDelay(i * 1000);
}
Console.ReadKey();
}
static async Task TestDelay(int expected) {
var startTime = DateTime.Now;
await Task.Delay(expected).ConfigureAwait(false);
var actual = (int) (DateTime.Now - startTime).TotalMilliseconds;
ThreadPool.GetAvailableThreads(out int aw, out _);
ThreadPool.GetMaxThreads(out int mw, out _);
Console.WriteLine("Thread: {3}, Total threads in pool: {4}, Expected: {0}, Actual: {1}, Diff: {2}", expected, actual, actual - expected, Thread.CurrentThread.ManagedThreadId, mw - aw);
Thread.Sleep(5000);
}
}
This program starts 100 tasks which await Task.Delay for 1-10 seconds, and then use Thread.Sleep for 5 seconds to simulate work on a thread on which continuation runs (this is thread pool thread). It will also output total number of threads in thread pool, so you will see how it increases over time.
If you run it you will see that in almost all cases (except first 8) - actual time after delay is much longer than expected, in some cases 5 times longer (you delayed for 3 seconds but 15 seconds has passed).
That's not because Task.Delay is so imprecise. The reason is continuation after await should be executed on a thread pool thread. Thread pool will not always give you a thread when you request. It can consider that instead of creating new thread - it's better to wait for one of the current busy threads to finish its work. It will wait for a certain time and if no thread became free - it will still create a new thread. If you request 10 thread pool threads at once and none is free, it will wait for Xms and create new one. Now you have 9 requests in queue. Now it will again wait for Xms and create another one. Now you have 8 in queue, and so on. This wait for a thread pool thread to become free is what causes increased delay in this console application (and most likely in your real program) - we keep thread pool threads busy with long Thread.Sleep, and thread pool is saturated.
Some parameters of heuristics used by thread pool are available for you to control. Most influential one is "minumum" number of threads in a pool. Thread pool is expected to always create new thread without delay until total number of threads in a pool reaches configurable "minimum". After that, if you request a thread, it might either still create new one or wait for existing to become free.
So the most straightforward way to remove this delay is to increase minimum number of threads in a pool. For example if you do this:
ThreadPool.GetMinThreads(out int wt, out int ct);
ThreadPool.SetMinThreads(100, ct); // increase min worker threads to 100
All tasks in the example above will complete at the expected time with no additional delay.
This is usually not recommended way to solve this problem though. It's better to avoid performing long running heavy operations on thread pool threads, because thread pool is a global resource and doing this affects your whole application. For example, if we remove Thread.Sleep(5000) in the example above - all tasks will delay for expected amount of time, because all what keeps thread pool thread busy now is Console.WriteLine statement which completes in no time, making this thread available for other work.
So to sum up: identify places where you perform heavy work on thread pool threads and avoid doing that (perform heavy work on separate, non-thread-pool threads instead). Alternatively, you might consider increasing minimum number of threads in a pool to a reasonable amount.

Does Thread.Sleep affect the ThreadPool?

I need to control one thread for my own purposes: calculating, waiting, reporting, etc...
In all other cases I'm using the ThreadPool or TaskEx.
In debugger, when I'm doing Thread.Sleep(), I notice that some parts of the UI are becoming less responsible. Though, without debugger seems to work fine.
The question is: If I'm creating new Thread and Sleep()'ing it, can it affect ThreadPool/Tasks?
EDIT: here are code samples:
One random place in my app:
ThreadPool.QueueUserWorkItem((state) =>
{
LoadImageSource(imageUri, imageSourceRef);
});
Another random place in my app:
var parsedResult = await TaskEx.Run(() => JsonConvert.DeserializeObject<PocoProductItem>(resultString, Constants.JsonSerializerSettings));
My ConcurrentQueue (modified, original is taken from here):
Creation of thread for Queue needs:
public void Process(T request, bool Async = true, bool isRecurssive = false)
{
if (processThread == null || !processThread.IsAlive)
{
processThread = new Thread(ProcessQueue);
processThread.Name = "Process thread # " + Environment.TickCount;
processThread.Start();
}
If one of the Tasks reports some networking problems, i want this thread to wait a bit
if (ProcessRequest(requestToProcess, true))
{
RequestQueue.Dequeue();
}
else
{
DoWhenTaskReturnedFalse();
Thread.Sleep(3000);
}
So, the question one more time: can Thread.Sleep(3000);, called from new Thread(ProcessQueue);, affect ThreadPool or TaskEx.Run() ?
Assuming that the thread you put on sleep was obtained from thread pool then surely it does affect the thread pool. If you explicitly say that the thread should sleep then it cannot be reused by the thread pool during this time. This may cause the thread pool to spawn new threads if there are some jobs awaiting to be scheduled. Creating a new thread is always expensive - threads are system resources.
You can however look at Task.Delay method (along with async and await) that suspends executing code in a more intelligent way - allowing the thread to be reused during waiting.
Refer to this Thread.Sleep vs. Task.Delay article.
Thread.Sleep() affects the thread it's called from, if you're calling Thread.Sleep() in a ThreadPool thread and trying to queue up more it may be hitting the max count of ThreadPool threads and waiting for a thread to finish before executing another.
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx
No, the Thread.Sleep() is only on the current thread. Thread.Sleep(int32) documentation:
The number of milliseconds for which the thread is suspended.

When to use and what is the difference of a timer and thread?

Just now have some confusion about timer and thread, see below example, Both codes provide the same result (Do some checking every 60 seconds), so when should I use a timer and when should I use a thread to handle jobs when they're providing the same result?
Use Thread:
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
Thread.Sleep(60000);
}
Use Timer:
public Form1()
{
InitializeComponent();
Timer time = new Timer();
time.Interval = 60000;
time.Tick += time_Tick;
time.Enabled = true;
}
void time_Tick(object sender, EventArgs e)
{
//Do Checking here
}
If the task that is performed periodically is very short, and will not get in the way of processing on the thread that the timer runs, then a timer is a reasonable choice.
On the other hand, if the periodic task takes a significant amount of time, and you cannot afford to have the main thread interrupted to perform it, then a separate dedicated thread is a good choice.
It depends on the timer you're using. If you're using a WinForms timer then your callback will fire on the gui thread. If you've got a lot of work to do then this will cause your application to block until you've finished, which will make for a bad user experience.
If you're using one of the other timers then they'll fire on a thread in the thread pool. Even here you'll want to avoid doing anything to long, but it won't block your gui thread. However, you're need to ensure you marshal any calls into the gui using the BeginInvoke method.
Starting your own thread is good if you're got long running tasks to do every time the timer fires, but once again you'll want to marshal calls back to the gui thread. Rather than using Thread.Sleep it's better to use an Event so that you can detect when the rest of the system is shutting down:
ManualResetEvent stopEvent = new ManualResetEvent(false);
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
while(stopEvent.Wait(60000) == false)
{
// Do processing
}
}
Now you can stop the thread by calling stopEvent.Set()
You can view a thread as a "sub-process"; a process can have multiple threads, allowing it to perform several operations in parallel. A thread is an expensive system resource; it uses a CPU when it's active, and allocates its own call stack (1MB by default). Using a thread to perform periodic actions is a waste of precious resources, and doesn't scale well.
A timer, in the other hand, is much cheaper. It's just a time-controlled trigger that does nothing most of the time, except when it's time to execute your code. It's the right choice in your case.
I would recommend to use Timer - it is more suitable when it comes to resource consumption.
Setting up a new thread is quite expansive.
By the way in case you would like to use Thread you should set it to IsBackground=true, so that it can finish its execution when the application is shutdown.

Aborting non working thread

I have a multi thread application written by c#, my max thread number is 256 and this application gets the performance counters of the computers in an Ip interval(192.168.1.0 -192.168.205.255)
it works fine and turns many times in a day. because I have to get reports.
But the problem is some times one machine keeps a thread and never finishes its work so my loop doesnt turn...
Are there any way to create threads with a countdown parameter. when I start the threads in foreach?
foreach(Thread t in threads)
{
t.start(); -----> t.start(countdownParameter) etc....
}
coundown parameter is the max life of each threads. This mean if a thread cant reach a machine it have to be abort. for example 60 seconds.. no not 256 machines, I meant 256 threads... there are about 5000 ip and 600 of them are alive. soo I am using 256 threads to read their values. and the other thing is loop. my loop is working as while all off the ipies finish it starts from beginning.
You can't specify a timeout for thread execution. However, you can try to Join each thread with a timeout, and abort it if it doesn't exit.
foreach(Thread t in threads)
{
t.Start();
}
TimeSpan timeOut = TimeSpan.FromSeconds(10);
foreach(Thread t in threads)
{
if (!t.Join(timeOut))
{
// Still not complete after 10 seconds, abort
t.Abort();
}
}
There are of course more elegant ways to do it, like using WaitHandles with the WaitAll method (note that WaitAll is limited to 64 handles at a time on most implementations, and doesn't work on STA threads, like the UI thread)
You should not terminate the thread from the outside. (Never kill a thread, make it commit suicide). Killing a thread can easily corrupt the state of an appdomain if you're not very careful.
You should rewrite the network code in the threads to either time out once the time-limit has been reached, or use asynchronous network code.
Usually a thread gets stuck on a blocking call (unless of course you have a bug causing an infinite loop). You need to identify which call is blocking and "poke" it to get it to unblock. It could be that your thread is waiting inside one of the .NET BCL waiting calls (WaitHandle.WaitOne, etc.) in which case you could use Thread.Interrupt to unblock it. But, in your case it is more likely that the API managing the communication with the remote computers is hung. Sometimes you can simply close the connection from a separate thread and that will unblock the hung method (as is the case with the Socket class). If all else fails then you really might have to fall back on the method of last of calling Thread.Abort. Just keep in mind that if you abort a thread it might corrupt the state of the app domain in which the abort originated or even the entire process itself. There were a lot of provisions added in .NET 2.0 that make aborts a lot safer than they were before, but there is still some risk.
You can use smth like this:
public static T Exec<T>(Func<t> F, int Timeout, out bool Completed)
{
T result = default(T);
Thread thread = new Thread(() => result = F());
thread.Start();
Completed = thread.Join(Timeout);
if(!Completed) thread.Abort();
return result;
}

Can a ThreadAbortException be raised during Thread.Sleep?

Can Thread.Abort interrupt a thread that is sleeping (using, say, Thread.Sleep(TimeSpan.FromDays(40)) ? Or will it wait until the sleep time span has expired ?
(Remarks: FromDays(40) is of course a joke. And I know Thread.Abort is not a recommended way to stop a thread, I'm working with legacy code that I don't want to refactor for now.)
Code is worth a thousand words:
public static void Main(string[] args)
{
var sleepy = new Thread(() => Thread.Sleep(20000));
sleepy.Start();
Thread.Sleep(100);
sleepy.Abort();
sleepy.Join();
}
The program ends before the sleep time is exhausted.
You can abort the thread from another thread only. That is, you should store the Thread reference somewhere and then call .Abort from a thread other than the one which is sleeping.

Categories

Resources