Locking method only for 2 threads - c#

I have following code:
public void Execute(IJobExecutionContext context)
{
lock (_lockObj)
{
// ... some HTTP job that can take 5 to 30 seconds ...
}
}
When an active job is working and a second thread enters the same method, I want it locked for second thread and wait.. However, when it is already locked for a second thread, and then a 3rd thread enters the code, I want it exit the method instead of waiting and entering job execution.
I could use a static counter variable and increase/decrease its value by the thread count within job execution. But I wonder if there is already a better practice to solve this issue.

You are looking for System.Threading.Semaphore.
var sem = new Semaphore(0, 2);
That creates a semaphore with an initial value of zero and a maximum of two. Up to two threads will be able to call sem.WaitOne() without blocking. After that, threads that call sem.WaitOne() will block until another thread calls sem.Release().
There is an overload WaitOne(int timeout) that accepts a timeout parameter. If zero is passed for the timeout, the call will not block, and return immediately. The boolean return value indicates whether or not you successfully acquired the semaphore. In your case, if it returns False, you simply abort the operation.

Use a Semaphore with a capacity of 2.

Related

Why is semaphore not released when given cancellationToken is cancelled

SemaphoreSlim has a WaitAsync() method that takes a CancellationToken. I'd expect the semaphore to get released when that token is cancelled, but this doesn't seem to be the case. Consider the code below:
var tokenSource = new CancellationTokenSource();
var semaphore = new SemaphoreSlim(1, 1);
// CurrentCount is 1
await semaphore.WaitAsync(tokenSource.Token);
// CurrentCount is 0 as we'd expect
tokenSource.Cancel(); // Token is cancelled
for(var i = 0; i< 10; i++)
{
var c = semaphore.CurrentCount; // Current count remains 0, even though token was cancelled
await Task.Delay(1000);
}
Even after the token gets cancelled, the CurrentCount remains at 0. I'm guessing this is by design, but what exactly is the CancellationToken used for if not to release the semaphore when the token is cancelled? Thanks!
Background
SemaphoreSlim Class
Represents a lightweight alternative to Semaphore that limits the
number of threads that can access a resource or pool of resources
concurrently.
...
The count is decremented each time a thread enters the semaphore, and
incremented each time a thread releases the semaphore. To enter the
semaphore, a thread calls one of the Wait or WaitAsync overloads. To
release the semaphore, it calls one of the Release overloads. When the
count reaches zero, subsequent calls to one of the Wait methods block
until other threads release the semaphore. If multiple threads are
blocked, there is no guaranteed order, such as FIFO or LIFO, that
controls when threads enter the semaphore.
SemaphoreSlim.CurrentCount
Gets the number of remaining threads that can enter the SemaphoreSlim
object.
...
The initial value of the CurrentCount property is set by the call to
the SemaphoreSlim class constructor. It is decremented by each call to
the Wait or WaitAsync method, and incremented by each call to the
Release method.
That's to say, every time you enter a semaphore you reduce the remaining threads that can enter. If you have entered successfully, the count is decremented.
Calling the CancellationToken that is being awaited only has an effect on threads awaiting the WaitAsync, or if you try to await the token again.
To answer the question, the CancellationToken is solely for the awaiting WaitAsync, it has no affect on how many threads can enter the SemaphoreSlim.
Furthermore
I think the real and pertinent question is, do you need to release a SemephoreSlim that has been cancelled! and the answer is no. An awaiting SemephoreSlim has not successfully entered or affected the count anyway, it's awaiting because there are no threads permissible.
And lastly, do you need release a SemephoreSlim that has been timed out via the timeout overload. The answer to that is, this method returns a bool as to whether it was entered successfully, that return value needs to be checked to determined whether it may need to be released.
Fun fact
This is the exact reason why you don't put the wait inside a try finally pattern that releases the slim.
// this can throw, or timeout
var result = await semaphore.WaitAsync(someTimeOut, tokenSource.Token);
if(!result)
return;
try
{
// synchronized work here
}
finally
{
semaphore.Release();
}
Releasing inappropriately will cause all sorts of problems and result in another exception sooner or later because you are exceeding the maximum count.

Force thread stop in .NET Core

Let's say i have .NET Core 2.0/2.1 program.
There is a thread executing the following method. I want to stop it forcefully.
Important notes:
Cooperative multitasking (for example, with CancellationToken) is a good thing, but not the case
XY problem (https://en.wikipedia.org/wiki/XY_problem) does exist, but i just want to know if stopping this thread is actually possible
while (true)
{
var i = 0;
try
{
Console.WriteLine($"Still alive {i++}");
}
catch (Exception e)
{
Console.WriteLine($"Caught {e.GetType().Name}");
}
}
Tried several options:
Thread.Abort - throws PlatformNotSupportedException, not an option
Thread.Interrupt - only works for threads in WaitSleepJoin state, which is not the case
Calling native API methods such as TerminateThread from kernel32.dll on Windows. This approach has a lot of problems like non-released locks (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85).aspx)
Concerns, from most important to least:
Releasing locks
Disposing objects in using directives
Actually collecting allocated objects
(as a corner case we can assume that out thread does not perform any heap allocations at all)
Use a ManualResetEventSlim. The instance will need to be available to both the thread you are trying to stop and the thread which will cause the stop.
In your while(true) loop, do something like this:
var shouldTerminate = mres.Wait(100);
if (shouldTerminate) { break; }
What this does is wait until the ManualResetEvent is put into a Set state, or 100ms, whichever comes first. The value returned indicates if the event is Set or Unset. You'll start off with the MRE in an Unset state, and when the control thread wishes to terminate the worker thread, it will call the Set method, and then it can Join the worker thread to wait for it to finish. This is important as in your loop you could perhaps be waiting on a network call to finish, and the worker won't actually terminate until you are back at the top of the loop again. If you need to, you could check the MRE with Wait at multiple points in the worker thread to prevent further expensive operations from continuing.

Multiple thread using ThreadPool and use of CountdownEvent

i got a example of CountdownEvent usage but when i go through the sample code then i just do not understand what it is doing and how CountdownEvent's Signal() and AddCount() help to synchronization for multiple thread.
here is the sample. please some one help me to understand how synchronization is working for multiple thread in this example where Signal() and AddCount() used.
class Program
{
static void Main(string[] args)
{
using (CountdownEvent e = new CountdownEvent(1))
{
// fork work:
for (int i = 1; i <= 5;i++ )
{
// Dynamically increment signal count.
TaskInfo ti = new TaskInfo("Current Thread ", i);
Console.WriteLine("Running thread " + e.CurrentCount);
e.AddCount();
ThreadPool.QueueUserWorkItem(delegate(object state)
{
try
{
//ProcessData(state);
TaskInfo inner_ti = (TaskInfo)state;
//Console.WriteLine(inner_ti.Boilerplate + inner_ti.Value);
Thread.Sleep(2000);
}
finally
{
Console.WriteLine("Signal thread " + e.CurrentCount);
e.Signal();
}
},
ti);
}
Console.WriteLine("Outer Signal thread " + e.CurrentCount);
e.Signal();
// The first element could be run on this thread.
// Join with work.
Console.WriteLine("Wait thread ");
e.Wait();
Console.WriteLine("ReadLine..... ");
Console.ReadLine();
}
}
}
public class TaskInfo
{
// State information for the task. These members
// can be implemented as read-only properties, read/write
// properties with validation, and so on, as required.
public string Boilerplate;
public int Value;
// Public constructor provides an easy way to supply all
// the information needed for the task.
public TaskInfo(string text, int number)
{
Boilerplate = text;
Value = number;
}
}
just guide me with small sample code like how Signal() and AddCount() is used in real life scenario for thread synchronization. thanks
The job of CountdownEvent is to provide a waitable object (i.e. an object that will block the current thread on request until some condition is satisfied), where the condition that needs to be satisfied is for the object's internal counter to reach the value of 0.
The code you've shown will initialize the CountdownEvent object with a count of 1. This value represents the main thread itself; the main thread will call Signal() later, indicating that it's completed its own work (which is to start five other threads).
For each new task that is created, the main thread increments — by calling the AddCount() method — the CountdownEvent object's counter by one before starting that new task (in this case, by queuing the task to the global thread pool). Each task, as it completes, will then decrement the object's counter by calling the Signal() method.
So initially, the code is repeatedly increasing the counter, from its initial value of 1, to its maximum value of 6.
Immediately after the tasks have been queued, the main thread decrements the counter to 5. Each task, as it completes, decrements the counter again. Five tasks means decrementing the counter five times, so when the last task completes, the counter will reach 0.
Remember: the point of the CountdownEvent object is to release a thread that is waiting on it when its internal counter reaches 0. (Or more specifically, for the waitable object to be set to its signaled, non-blocking state).
The main thread calls the Wait() method on the CountdownEvent object, which initially causes the main thread to be blocked (i.e. to wait). It will continue to wait until the CountdownEvent is set to the non-blocking state, which occurs when its internal counter reaches 0, which occurs when the last task completes.
Thus, the main thread waits until the last task completes.
just guide me with small sample code like how Signal() and AddCount() is used in real life scenario for thread synchronization
The code example you've posted here seems "real" enough. My description above explains how the code example works. You would use the CountdownEvent object in any scenario where you have some specific count of operations, tasks, events, etc. that should occur before some specific thread should continue after waiting.
Of course, not all synchronization scenarios involve this kind of requirement. There are other, different synchronization mechanisms that can be used for those other scenarios. The CountdownEvent is specifically for those scenarios where the waiting of a thread is unblocked by the completion of a countdown, hence the name of the class.

How to estimate method execution time?

I have requirement to cancel method execution if it takes the more than two seconds to complete and restart it on another thread.
So, is there any way/call back mechanism/HACK, I can make method inform me that it crossed 2 seconds time limit?
check if network drive exists with timeout in c#
https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time
Async Pattern:
public static T SafeLimex<T>(Func<T> F, int Timeout, out bool Completed)
{
var iar = F.BeginInvoke(null, new object());
if (iar.AsyncWaitHandle.WaitOne(Timeout))
{
Completed = true;
return F.EndInvoke(iar);
}
F.EndInvoke(iar); //not calling EndInvoke will result in a memory leak
Completed = false;
return default(T);
}
You should create System.Threading.Timer on two seconds, and run your method in another thread and wait for callback from it, if method completes before timer runs you should dispose timer, otherwise you should abort thread in which you method are executing. This is pretty simple for example
using (new Timer(BreakFunction, true, TimeSpan.FromMinutes(2), Timeout.Infinite))
{
//TODO:here you should create another thread that will run your method
}
In BreakFunction you should abort thread that runs your methods
It would be good if you can find it. I've been looking for it too.
What I usually do is start the method in another Thread, and start a Timer with 2 seconds in this case. The first time it raises the event, just do:
if (a.IsAlive)
{
a.Abort();
}
Two important things:
The Thread declared should be visible by the method that handles the timer
When calling Abort(), it raises ThreadAbortException, so you should correctly handle it in the method.

Why is my code stopping and not returning an exception?

I have some code that starts a couple of threads to let them execute, then uses a while loop to check for the current time passing a set timeout period, or for the correct number of results to have been processed (by checking an int on the class object) (with a Thread.Sleep() to wait between loops)
Once the while loop is set to exit, it calls Abort() on the threads and should return data to the function that calls the method.
When debugging and stepping through the code, I find there can be exceptions in the code running on the separate threads, and in some cases I handle these appropriately, and at other times I don't want to do anything specific.
What I have been seeing is that my code goes into the while loop and the thread sleeps, then nothing is returned from my function, either data or an exception. Code execution just stops completely.
Any ideas what could be happening?
Code sample:
System.Threading.Thread sendThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Send));
sendThread.Start();
System.Threading.Thread receiveThread =
new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
receiveThread.Start();
// timeout
Int32 maxSecondsToProcess = this.searchTotalCount * timeout;
DateTime timeoutTime = DateTime.Now.AddSeconds(maxSecondsToProcess);
Log("Submit() Timeout time: " + timeoutTime.ToString("yyyyMMdd HHmmss"));
// while we're still waiting to receive results & haven't hit the timeout,
// keep the threads going
while (resultInfos.Count < this.searchTotalCount && DateTime.Now < timeoutTime)
{
Log("Submit() Waiting...");
System.Threading.Thread.Sleep(10 * 1000); // 1 minute
}
Log("Submit() Aborting threads"); // <== this log doesn't show up
sendThread.Abort();
receiveThread.Abort();
return new List<ResultInfo>(this.resultInfos.Values);
So, you really shouldn't use the Sleep method on the thread for synchronization purposes. This is what synchronization classes such as ManualResetEvent are for, as well as the Asynchronous Programming Model (IAsyncResult implementations).
A better approach here would be to create a delegate with the signature of the method you want to run asynchronously. Then, assign the method group that is the entry point for the asynchronous operation to an instance of that delegate and call BeginInvoke on the delegate instance.
From there, you would run your loop, expect you would call the overload of WaitOne on the WaitHandle returned by the AsyncWaitHandle property of the IAsyncResult implementation returned by the call to BeginInvoke on the delegate.
This will cause less reliance on the Sleep method (which is bad for synchronization in general).
If you have the option to use .NET 4.0, then you might want to take a look at the Task class in the System.Threading.Tasks namespace as it provides an even better way to handle asynchronous processing, cancellation, and wait timeouts.
Thread.Abort Raises a ThreadAbortException in the thread on which it is invoked
You shouldn't let exceptions escape from your threads ever - you should have exception handling in your threaded object. At the very least there should be a try\catch block around the code in the threaded object.

Categories

Resources