Calling methods from different threads - c#

I have 4 windows forms and they use one method of one another form. This method must be processed just by one of the forms. If a thread wants to use this method, it must be sure that method is not called at this time by other threads.
I have a solution like that
bool methodIsBusy = false;
void Method()
{
methodIsBusy = true;
//do method things
//done method things
methodIsBusy = false;
}
and use methodIsBusy to know that method is occupied by a thread or not. Are any more creative solutions to this problem? Thanks.

The simplest traditional pattern would be more like this, using lock. Code inside of a lock (referred to as a critical section) can only be executed by one thread at a time.
object lockObject = new object(); //Can be anything, an object will do
void Method()
{
lock (lockObject)
{
//do method things
//done method things
}
}
You could in theory use a bool but you'd have to write busywait code, like this:
//Don't do this!
while (methodIsBusy)
{
System.Threading.Thread.Sleep(10); //or some number
}
This kind of code will end up using more resources than a lock, which is designed for exactly this purpose.

You can use a lock to ensure that only one thread can enter a critical block capsuled with a lock statement.

Also have a look at Monitor.TryEnter - which allows you to test if you can enter, not lock and go out w/o doing somth. Just make really sure to use a try {} finalley { Monitor.Exit(obj); } to release your lock obj again.

Related

Lock for different methods but same variable

Hello friends have a doubt in threaded application.
class sample
{
static volatile bool _shutdownThreads;
static readonly object _lockerObject = new object();
main()
{
create thread for samplemethod()
lock(_lockerObject)
{
_shutdownThreads = true;
}
}
samplemethod()
{
while(true)
{
lock(_lockerObject)
{
if(_shutdownThreads) break;
}
}
}
}
(1)ok i guess you might have understood what i am trying to accomplish. I need to have a safe way to use the _shutdownThreads variable. is this the right approach?
(2)if i lock a block of code all the variables inside the block gets locked too? i mean even other threads(for example main) cant access the variable. am i right?
Yes, you are right. The purpose of lock is to let one thread access a code block while other threads will wait. However in your specific case: it does not make sense to lock a boolean assignment. This will be atomic anyway.
"I need to have a safe way to use the _shutdownThreads variable. is
this the right approach?"
Yes, and no. It's safe, but you have a busy loop that will use A LOT of CPU for no good reason. There are better options for waiting for an event, but you can at least make it a lot less horrific by making the thread sleep a while between each check:
while(true) {
lock(_lockerObject) {
if(_shutdownThreads) break;
}
Thread.Sleep(100);
}
"if i lock a block of code all the variables inside the block gets
locked too?"
No, not at all. The lock doesn't keep any other thread from accessing any data what so ever. The only thing that the lock does is keeping any other thread from entering a code block that uses the same identifier reference (_lockerObject in your case).
To protect the data, you have to use locks around every code block that accesses the data, using the same identifier reference.

Under what conditions can a thread enter a lock (Monitor) region more than once concurrently?

(question revised): So far, the answers all include a single thread re-entering the lock region linearly, through things like recursion, where you can trace the steps of a single thread entering the lock twice. But is it possible somehow, for a single thread (perhaps from the ThreadPool, perhaps as a result of timer events or async events or a thread going to sleep and being awaken/reused in some other chunk of code separately) to somehow be spawned in two different places independently of each other, and hence, run into the lock re-entrance problem when the developer didn't expect it by simply reading their own code?
In the ThreadPool Class Remarks (click here) the Remarks seem to suggest that sleeping threads should be reused when they're not in use, or otherwise wasted by sleeping.
But on the Monitor.Enter reference page (click here) they say "It is legal for the same thread to invoke Enter more than once without it blocking." So I figure there must be something I'm supposed to be careful to avoid. What is it? How is it even possible for a single thread to enter the same lock region twice?
Suppose you have some lock region that takes an unfortunately long time. This might be realistic, for example, if you access some memory that has been paged out (or whatever.) The thread in the locked region might go to sleep or something. Does the same thread become eligible to run more code, which might accidentally step into the same lock region? The following does NOT, in my testing, get multiple instances of the same thread to run into the same lock region.
So how does one produce the problem? What exactly do you need to be careful to avoid?
class myClass
{
private object myLockObject;
public myClass()
{
this.myLockObject = new object();
int[] myIntArray = new int[100]; // Just create a bunch of things so I may easily launch a bunch of Parallel things
Array.Clear(myIntArray, 0, myIntArray.Length); // Just create a bunch of things so I may easily launch a bunch of Parallel things
Parallel.ForEach<int>(myIntArray, i => MyParallelMethod());
}
private void MyParallelMethod()
{
lock (this.myLockObject)
{
Console.Error.WriteLine("ThreadId " + Thread.CurrentThread.ManagedThreadId.ToString() + " starting...");
Thread.Sleep(100);
Console.Error.WriteLine("ThreadId " + Thread.CurrentThread.ManagedThreadId.ToString() + " finished.");
}
}
}
Suppose you have a queue that contains actions:
public static Queue<Action> q = whatever;
Suppose Queue<T> has a method Dequeue that returns a bool indicating whether the queue could be successfully dequeued.
And suppose you have a loop:
static void Main()
{
q.Add(M);
q.Add(M);
Action action;
while(q.Dequeue(out action))
action();
}
static object lockObject = new object();
static void M()
{
Action action;
lock(lockObject)
{
if (q.Dequeue(out action))
action();
}
}
Clearly the main thread enters the lock in M twice; this code is re-entrant. That is, it enters itself, through an indirect recursion.
Does this code look implausible to you? It should not. This is how Windows works. Every window has a message queue, and when a message queue is "pumped", methods are called corresponding to those messages. When you click a button, a message goes in the message queue; when the queue is pumped, the click handler corresponding to that message gets invoked.
It is therefore extremely common, and extremely dangerous, to write Windows programs where a lock contains a call to a method which pumps a message loop. If you got into that lock as a result of handling a message in the first place, and if the message is in the queue twice, then the code will enter itself indirectly, and that can cause all manner of craziness.
The way to eliminate this is (1) never do anything even slightly complicated inside a lock, and (2) when you are handling a message, disable the handler until the message is handled.
Re-Entrance is possible if you have a structure like so:
Object lockObject = new Object();
void Foo(bool recurse)
{
lock(lockObject)
{
Console.WriteLine("In Lock");
if (recurse) { foo(false); }
}
}
While this is a pretty simplistic example, it's possible in many scenarios where you have interdependent or recursive behaviour.
For example:
ComponentA.Add(): locks a common 'ComponentA' object, adds new item to ComponentB.
ComponentB.OnNewItem(): new item triggers data-validation on each item in list.
ComponentA.ValidateItem(): locks a common 'ComponentA' object to validate the item.
Same-thread re-entry on the same lock is needed to ensure you don't get deadlocks occurring with your own code.
One of the more subtle ways you can recurse into a lock block is in GUI frameworks. For example, you can asynchronously invoke code on a single UI thread (a Form class)
private object locker = new Object();
public void Method(int a)
{
lock (locker)
{
this.BeginInvoke((MethodInvoker) (() => Method(a)));
}
}
Of course, this also puts in an infinite loop; you'd likely have a condition by which you'd want to recurse at which point you wouldn't have an infinite loop.
Using lock is not a good way to sleep/awaken threads. I would simply use existing frameworks like Task Parallel Library (TPL) to simply create abstract tasks (see Task) to creates and the underlying framework handles creating new threads and sleeping them when needed.
IMHO, Re-entering a lock is not something you need to take care to avoid (given many people's mental model of locking this is, at best, dangerous, see Edit below). The point of the documentation is to explain that a thread cannot block itself using Monitor.Enter. This is not always the case with all synchronization mechanisms, frameworks, and languages. Some have non-reentrant synchronization in which case you have to be careful that a thread doesn't block itself. What you do need to be careful about is always calling Monitor.Exit for every Monitor.Enter call. The lock keyword does this for you automatically.
A trivial example with re-entrance:
private object locker = new object();
public void Method()
{
lock(locker)
{
lock(locker) { Console.WriteLine("Re-entered the lock."); }
}
}
The thread has entered the lock on the same object twice so it must be released twice. Usually it is not so obvious and there are various methods calling each other that synchronize on the same object. The point is that you don't have to worry about a thread blocking itself.
That said you should generally try to minimize the amount the time you need to hold a lock. Acquiring a lock is not computationally expensive, contrary to what you may hear (it is on the order of a few nanoseconds). Lock contention is what is expensive.
Edit
Please read Eric's comments below for additional details, but the summary is that when you see a lock your interpretation of it should be that "all activations of this code block are associated with a single thread", and not, as it is commonly interpreted, "all activations of this code block execute as a single atomic unit".
For example:
public static void Main()
{
Method();
}
private static int i = 0;
private static object locker = new object();
public static void Method()
{
lock(locker)
{
int j = ++i;
if (i < 2)
{
Method();
}
if (i != j)
{
throw new Exception("Boom!");
}
}
}
Obviously, this program blows up. Without the lock, it is the same result. The danger is that the lock leads you into a false sense of security that nothing could modify state on you between initializing j and evaluating the if. The problem is that you (perhaps unintentionally) have Method recursing into itself and the lock won't stop that. As Eric points out in his answer, you might not realize the problem until one day someone queues up too many actions simultaneously.
ThreadPool threads cannot be reused elsewhere just because they went to sleep; they need to finish before they're reused. A thread that is taking a long time in a lock region does not become eligible to run more code at some other independent point of control. The only way to experience lock re-entry is by recursion or executing methods or delegates inside a lock that re-enter the lock.
Let's think about something other than recursion.
In some of business logics, they would like to control the behaviors of synchronization.
One of these patterns, they invoke Monitor.Enter somewhere and would like to invoke Monitor.Exit elsewhere later. Here is the code to get the idea about that:
public partial class Infinity: IEnumerable<int> {
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<int> GetEnumerator() {
for(; ; )
yield return ~0;
}
public static readonly Infinity Enumerable=new Infinity();
}
public partial class YourClass {
void ReleaseLock() {
for(; lockCount-->0; Monitor.Exit(yourLockObject))
;
}
void GetLocked() {
Monitor.Enter(yourLockObject);
++lockCount;
}
void YourParallelMethod(int x) {
GetLocked();
Debug.Print("lockCount={0}", lockCount);
}
public static void PeformTest() {
new Thread(
() => {
var threadCurrent=Thread.CurrentThread;
Debug.Print("ThreadId {0} starting...", threadCurrent.ManagedThreadId);
var intanceOfYourClass=new YourClass();
// Parallel.ForEach(Infinity.Enumerable, intanceOfYourClass.YourParallelMethod);
foreach(var i in Enumerable.Range(0, 123))
intanceOfYourClass.YourParallelMethod(i);
intanceOfYourClass.ReleaseLock();
Monitor.Exit(intanceOfYourClass.yourLockObject); // here SynchronizationLockException thrown
Debug.Print("ThreadId {0} finished. ", threadCurrent.ManagedThreadId);
}
).Start();
}
object yourLockObject=new object();
int lockCount;
}
If you invoke YourClass.PeformTest(), and get a lockCount greater than 1, you've reentered; not necessarily be concurrent.
If it was not safe for reentrancy, you will get stuck in the foreach loop.
In the code block where Monitor.Exit(intanceOfYourClass.yourLockObject) will throw you a SynchronizationLockException, it is because we are trying to invoke Exit more than the times it have entered. If you are about to use the lock keyword, you possibly would not encounter this situation except directly or indirectly of recursive calls. I guess that's why the lock keyword was provided: it prevents the Monitor.Exit to be omitted in a careless manner.
I remarked the calling of Parallel.ForEach, if you are interested then you can test it for fun.
To test the code, .Net Framework 4.0 is the least requirement, and following additional name spaces are required, too:
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.Collections;
Have fun.

C# manual lock/unlock

I have a function in C# that can be called multiple times from multiple threads and I want it to be done only once so I thought about this:
class MyClass
{
bool done = false;
public void DoSomething()
{
lock(this)
if(!done)
{
done = true;
_DoSomething();
}
}
}
The problem is _DoSomething takes a long time and I don't want many threads to wait on it when they can just see that done is true.
Something like this can be a workaround:
class MyClass
{
bool done = false;
public void DoSomething()
{
bool doIt = false;
lock(this)
if(!done)
doIt = done = true;
if(doIt)
_DoSomething();
}
}
But just doing the locking and unlocking manually will be much better.
How can I manually lock and unlock just like the lock(object) does? I need it to use same interface as lock so that this manual way and lock will block each other (for more complex cases).
The lock keyword is just syntactic sugar for Monitor.Enter and Monitor.Exit:
Monitor.Enter(o);
try
{
//put your code here
}
finally
{
Monitor.Exit(o);
}
is the same as
lock(o)
{
//put your code here
}
Thomas suggests double-checked locking in his answer. This is problematic. First off, you should not use low-lock techniques unless you have demonstrated that you have a real performance problem that is solved by the low-lock technique. Low-lock techniques are insanely difficult to get right.
Second, it is problematic because we don't know what "_DoSomething" does or what consequences of its actions we are going to rely on.
Third, as I pointed out in a comment above, it seems crazy to return that the _DoSomething is "done" when another thread is in fact still in the process of doing it. I don't understand why you have that requirement, and I'm going to assume that it is a mistake. The problems with this pattern still exist even if we set "done" after "_DoSomething" does its thing.
Consider the following:
class MyClass
{
readonly object locker = new object();
bool done = false;
public void DoSomething()
{
if (!done)
{
lock(locker)
{
if(!done)
{
ReallyDoSomething();
done = true;
}
}
}
}
int x;
void ReallyDoSomething()
{
x = 123;
}
void DoIt()
{
DoSomething();
int y = x;
Debug.Assert(y == 123); // Can this fire?
}
Is this threadsafe in all possible implementations of C#? I don't think it is. Remember, non-volatile reads may be moved around in time by the processor cache. The C# language guarantees that volatile reads are consistently ordered with respect to critical execution points like locks, and it guarantees that non-volatile reads are consistent within a single thread of execution, but it does not guarantee that non-volatile reads are consistent in any way across threads of execution.
Let's look at an example.
Suppose there are two threads, Alpha and Bravo. Both call DoIt on a fresh instance of MyClass. What happens?
On thread Bravo, the processor cache happens to do a (non-volatile!) fetch of the memory location for x, which contains zero. "done" happens to be on a different page of memory which is not fetched into the cache quite yet.
On thread Alpha at the "same time" on a different processor DoIt calls DoSomething. Thread Alpha now runs everything in there. When thread Alpha is done its work, done is true and x is 123 on Alpha's processor. Thread Alpha's processor flushes those facts back out to main memory.
Thread bravo now runs DoSomething. It reads the page of main memory containing "done" into the processor cache and sees that it is true.
So now "done" is true, but "x" is still zero in the processor cache for thread Bravo. Thread Bravo is not required to invalidate the portion of the cache that contains "x" being zero because on thread Bravo neither the read of "done" nor the read of "x" were volatile reads.
The proposed version of double-checked locking is not actually double-checked locking at all. When you change the double-checked locking pattern you need to start over again from scratch and re-analyze everything.
The way to make this version of the pattern correct is to make at least the first read of "done" into a volatile read. Then the read of "x" will not be permitted to move "ahead" of the volatile read to "done".
You can check the value of done before and after the lock:
if (!done)
{
lock(this)
{
if(!done)
{
done = true;
_DoSomething();
}
}
}
This way you won't enter the lock if done is true. The second check inside the lock is to cope with race conditions if two threads enter the first if at the same time.
BTW, you shouldn't lock on this, because it can cause deadlocks. Lock on a private field instead (like private readonly object _syncLock = new object())
The lock keyword is just syntactic sugar for the Monitor class. Also you could call Monitor.Enter(), Monitor.Exit().
But the Monitor class itself has also the functions TryEnter() and Wait() which could help in your situation.
I know this answer comes several years late, but none of the current answers seem to address your actual scenario, which only became apparent after your comment:
The other threads don't need to use any information generated by ReallyDoSomething.
If the other threads don't need to wait for the operation to complete, the second code snippet in your question would work fine. You can optimize it further by eliminating your lock entirely and using an atomic operation instead:
private int done = 0;
public void DoSomething()
{
if (Interlocked.Exchange(ref done, 1) == 0) // only evaluates to true ONCE
_DoSomething();
}
Furthermore, if your _DoSomething() is a fire-and-forget operation, then you might not even need the first thread to wait for it, allowing it to run asynchronously in a task on the thread pool:
int done = 0;
public void DoSomething()
{
if (Interlocked.Exchange(ref done, 1) == 0)
Task.Factory.StartNew(_DoSomething);
}

Synchronization primitive "lock once"

I need a synchronization primitive which is similar to Monitor but doesn't require to Exit it as many times as I have enter it. If I enter Monitor by one thread and then reenter it by the same thread I will need to call Monitor.Exit twice. But I need to exit it by one call.
Now I use a some kind of Monitor wrapper which doesn't enter Monitor if it was already entered by current thread (and that's why then I can exit it by one call). But may be .NET Framework contains one?
I'm curious to know why you would ever call Monitor.Enter multiple times without an equal number of calls to Monitor.Exit. Typically any such synchronization code would look like this:
try
{
Monitor.Enter(lockObject);
// some code that needs to be synchronized
}
finally
{
Monitor.Exit(lockObject);
}
Assuming you are using try/finally wherever you acquire a lock using Monitor.Enter (which you should be), I'm having trouble seeing why you would need this "lock-once" class you're asking about.
In fact, you should basically never have to do this yourself anyway, as a much simpler approach that does essentially the same thing is to use a lock statement:
lock (lockObject)
{
// some code that needs to be synchronized
}
That said, I could certainly just be missing something.
how do you know it's the same thread and how to you ensure that when this threads leaves it is going to call exit before it leaves?
From the looks of it, you just need something else (in an outer level) that has the lock. Maybe an "entry point" method that locks and calls another method that has the meat of the work then you can call this other method many times without going past the lock.
public static void MethodOne()
{
lock (lockObj)
{
MethodTwo();
}
}
private static void MethodTwo()
{
//This method can be called multiple times
//without going past MethodOne and so you only
//lock once
}
private static void MethodThree()
{
}

How to restrict to one method call at a time?

I'd like to know how to implement the following restriction: One method in my Windows Service should not be called again before the earlier call has been finished. The method in question goes thru couple of database tables and it's very important that this process won't be called again before it's finished. I have a setting that defines how often my service will activate and under normal circumstances it never activates before the earlier call has been finished (because whole process should not take more than couple of minutes and the interval is set to 10 minutes) but thats not sure enough. I guess.
How to implement this?
You can use a named Mutex or a named Semaphore to ensure that only one holder of the Mutex/Semaphore is executing at once. As a commenter pointed out, keep in mind you must be careful not to abandon a mutex or improperly acquire/release a semaphore.
One way would be to use locking:
private readonly object myLock = new object();
private void MyMethod()
{
lock(myLock)
{
//code goes here
}
}
This ensures that this method can never be running more that once at a time.
I second the Mutex suggestion, but you might also want to take a look at transactions. Wrap your entire code in a transaction (this requires a using System.Transactions):
using(TransactionScope scope = new TransactionScope())
{
try
{
/* ... your current code here */
scope.Complete();
}
catch (Exception e)
{
/* Any appropriate error handling/logging here */
}
finally
{
}
}
A transactionscope automatically locks all related tables. You can reduce the restrictions and allow other processes to read, but not write to the data that your process is touching. You do this by passing options to the TransactionsScope constructor.
Well if all the code is localized you can set a boolean and check the boolean before executing the method, otherwise you can IPC and request the state before execution.
Some alternatives:
You can put a check in the call to check some flag or call Monitor.TryEnter and return with an error/do nothing if negative.
You can queue up calls (if you need this method to execute more than once) and only invoke when Monitor has been signaled.
If you don't mind blocking, and the method is on a separate thread, you can join the thread of the method you want to wait.
I'm sure there are others.
If you don't mind restricting one thread at a time to the entire object, then you can use:
Synchronization Contexts
Have your class inherit from ContextBoundObject
Apply a [Synchronization] attribute to the class.
The CLR will only allow one thread at a time to execute code per instance of this class. The others will block until the lock is released by the current thread.
This sounds like a serial workflow... Have you considered using a workflow framework?
If you want your function run with await/async
private static readonly SemaphoreSlim yourLock = new SemaphoreSlim(1, 1); //allow only 1 thread at time
...
private async Task<string> YourFunction() {
await yourLock.WaitAsync();
try
{
//your code go here
}
finally
{
yourLock.Release();
}
}

Categories

Resources