How to implement simple multithreaded function - c#

I need to implement simple function that is called from multiple threads. The logic of the function is simple - think of horse races - only the first horse can get golden medal once we have a winner the race is over.
class ConditionalOrderGroup
{
private volatile bool _locked = false;
private List<ConditionalOrder> _ConditionalOrderList = null;
public bool LockGroup(ConditionalOrder initiator)
{
// this is finishline - we need to let only the first one proceed
if (_locked)
return false;
else
{
_locked = true;
}
// this is what winner gets
foreach (ConditionalOrder order in _ConditionalOrderList)
{
\\ cancel other orders
}
return true;
}
}
I am not happy with
if (_locked)
return false;
else
{
_locked = true;
}
What if two orders can pass if check and proceed to else. How to rewrite this code
without using lock statement?
UPDATE
I mean my goal is not use any blocking method like lock statement.

You need a separate, private object and use the built-in locking:
private object padLock = new object(); // 1-to-1 with _ConditionalOrderList
if (Monitor.TryEnter(padLock))
{
try
{
// cancel other orders
return true;
}
finally
{
Monitor.Exit(padLock);
}
}
else
{
return false;
}

Use Interlocked class to change values of the variable in a thread safe way.

Expanding on what decyclone said about interlocked, this is exactly how you would do it:
const int LOCKED = 1;
const int UNLOCKED = 0;
volatile int lockState = UNLOCKED;
public bool Foo()
{
try
{
//locking
//compare exchange returns the value that was in lockState before the compareExchange operation, so from that you can determine if you grabbed the lock or not
//if it was locked before, then you know the lock is not yours
if (Interlocked.CompareExchange(ref lockState, UNLOCKED, LOCKED) == LOCKED)
return false;
//lock is yours, do whatever stuff you like here, including throw exceptions
}
finally
{
//unlocking
//because this is in finally this lock will be released even if something goes wrong with your code
Interlocked.Exchange(ref lockstate, UNLOCKED);
}
}

Related

Best solution for stopping a piece of code to be called multiple times?

I have a method which is been called every 1 hour. But sometimes the method operations are not been completed fully within one hour and the method is again been called which causes confusion. So I have to find out if the previous method is been completed. Which is the best solution for this problem?
// will be called for every one hour where the value will be repeated
// At sometimes it is possible for the same value to be called continually
for the next hour and at that time problem occurs
Void Method(int value)
{
If(value =0)
// Do some operations which may exceed one hour
Else If(value =1)
// Do some operation’s which may exceed one hour
.
.
.
}
Thanks,
One question would be what do you want to happen if the method is called while it is still running?
This code will just drop the 2nd call
private bool _running = false;
private readonly object _lock = new object();
void Method(int value)
{
lock (_lock)
{
if (_running)
{
return;
}
else
{
_running = true;
}
}
if (value == 0)
{
// Do some operations which may exceed one hour
}
else if (value == 1)
{
// Do some operation’s which may exceed one hour
}
_running = false;
}
A simple idea is to save the state in a class field, so that the method checks to see if it's free to do some work or not. This will mean that if you call the method and it's busy, the work won't happen for your call:
private static bool methodIsBusy = false;
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// If we're busy, return right away
if (methodIsBusy) return;
// Let future calls know we're busy
methodIsBusy = true;
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
// Allow future calls to run now
methodIsBusy = false;
}
Our test method:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
(Only the first of the three messages was printed)
Another idea is to use a lock, which means that calls to the method will pile up if the method is busy. All calls will eventually get completed, but if every call is longer than the iteration time in which the method is called, it will get further and further behind:
private static object methodLocker = new object();
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// Lock on a common object, so this call will wait
// until there are no locks before it can continue
lock (methodLocker)
{
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
}
}
Our test method again:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
}
Output
(Notice the difference between when the message was called and when it executed gets longer each time)

Howto avoid concurrently calling a method without blocking?

I want to run a cleanup task that might run for several seconds. Multiple threads could call this task but I want to run this task only once. All other invokations should just skip.
The following is my current implementation but I cannot imagine there is not a better solution in the .net framework resulting in less lines of code.
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
Yes, there is a better solution. You can use Interlocked.CompareExchange, the code becomes simpler and lock-free:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
In this case Interlocked.CompareExchange does the following as an atomic operation (pseudo-code):
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
From the MSDN documentation:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is
stored in location1. Otherwise, no operation is performed. The compare
and exchange operations are performed as an atomic operation. The
return value of CompareExchange is the original value in location1,
whether or not the exchange takes place

How to lock a part of method from another threads?

How can i lock a part of method in c# from another threads?
I mean if one of threads was here, then exit...
For example:
if(threads[0].WasHere)
{
return;
}
an effective way is with an interlocked exchange; by setting some token field to a non-default value during the work, the other threads can check this and exit. For example:
private int hazWorker; // = 0 - put this at the scope you want to protect
then:
// means: atomically set hazWorker to 1, but only if the old value was 0, and
// tell me what the old value was (and compare that result to 0)
if(Interlocked.CompareExchange(ref hazWorker, 1, 0) != 0) {
return; // someone else has the conch
}
try {
// your work here
} finally {
Interlocked.Exchange(ref hazWorker, 0); // set it back to default
}
You can use Monitor.TryEnter for this purpose.
if(!Monitor.TryEnter(someLock))
{
return;
}
try
{
//Critical region
}
finally
{
Monitor.Exit(someLock);
}
Or more reliable way to fight with Rude Thread aborts (suggested by marc in comments)
bool lockTaken = false;
try
{
Monitor.TryEnter(someLock, ref lockTaken);
if (lockTaken)
{
//Critical region
}
}
finally
{
if(lockTaken) Monitor.Exit(someLock);
}
Note that this doesn't checks for threads[0] still working, rather it checks whether any other thread is in Critical region. If so, it exits the method.
You can use a bool value - assign it "false" on default, and then the first of the threads sets it to "true". And then the piece of code could look like this:
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
I would also put the code in a lock to make sure only one thread executes it at time (to deal with any possible race conditions), like below.
The lockVariable is a locker variable and it can be of any reference type, ex. object lockVariable = new object();
lock (lockVariable)
{
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
}

C# "ref" not Doing what I Think it Should

I have a class that talks to an external .exe. The class has a bunch of similar methods; they call a function of the .exe, wait for response, and then return true or false.
The response comes in the form of events that change the values of fields of this class.
Simplified code:
class Manager
{
private static bool connected = false;
public static bool Connect()
{
runtime.Connect();
int secondsWaited = 0;
while (!connected)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
}
The other methods use the same call-wait-loop-return structure.
My goal is to make a single method to do this waiting for me, like so:
private static bool WaitReferenceEqualsValue<T>(ref T reference, T value)
{
int secondsWaited = 0;
while (!reference.Equals(value))
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
Then each method would do:
runtime.DoSomething();
return WaitReferenceEqualsValue<someType>(ref someField, someSuccessfulValue);
However, when I replace the wait-loop with this method call, the field "connected", even though passed in as a reference, always stays the same.
Any idea what's going on here, and how to get the desired functionality?
Thanks in advance.
EDIT:
public static bool Connect()
{
...
runtime.Connect();
// this code works
/*int secondsWaited = 0;
while (connected != true)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}*/
// this somehow blocks OnConnect from firing, so connected never gets set to true
lock (typeof(SkypeKitManager))
{
WaitReferenceEqualsValue<bool>(ref connected, true);
}
...
}
OnConnect:
private static void OnConnect(object sender, Events.OnConnectArgs e)
{
if (e != null && e.success)
{
lock (typeof(Manager))
{
connected = true;
}
}
}
You're not doing any synchronization on that field although you access it from multiple threads and one of them is writing. This is a race (no exception! this is a race even if it looks safe. It isn't safe.).
Probably the JIT enregistered it which is a common optimization. It just never gets read from memory, always from a register. Add synchronization (for example a lock, or Interlocked or Volatile methods).
Your usage of ref is correct.
The problem with your code is essentially compiler optimization. Fo optimization purpose compilers (or jits) necessarily take a pretty much single threaded view. The compiler/jit will then notice that you don't touch reference in your code at all, therefore it can move the comparison outside the loop. It is free to do so, since you basically create a race condition (no synchronization/atomic accesses).
Fixing it could either involve using synchronization mechanisms or add the volatile specifier to reference, thus telling the compiler/jit, that the variable can be changed from outside the method.

Interlocked used to increment/mimick a boolean, is this safe?

I'm just wondering whether this code that a fellow developer (who has since left) is OK, I think he wanted to avoid putting a lock. Is there a performance difference between this and just using a straight forward lock?
private long m_LayoutSuspended = 0;
public void SuspendLayout()
{
Interlocked.Exchange(ref m_LayoutSuspended, 1);
}
public void ResumeLayout()
{
Interlocked.Exchange(ref m_LayoutSuspended, 0);
}
public bool IsLayoutSuspended
{
get { return Interlocked.Read(ref m_LayoutSuspended) != 1; }
}
I was thinking that something like that would be easier with a lock? It will indeed be used by multiple threads, hence why the use of locking/interlocked was decided.
Yes what you are doing is safe from a race point of view reaching the m_LayoutSuspended field, however, a lock is required for the following reason if the code does the following:
if (!o.IsLayoutSuspended) // This is not thread Safe .....
{
o.SuspendLayout(); // This is not thread Safe, because there's a difference between the checck and the actual write of the variable a race might occur.
...
o.ResumeLayout();
}
A safer way, that uses CompareExchange to make sure no race conditions have occurred:
private long m_LayoutSuspended = 0;
public bool SuspendLayout()
{
return Interlocked.CompareExchange(ref m_LayoutSuspended, 1) == 0;
}
if (o.SuspendLayout())
{
....
o.ResumeLayout();
}
Or better yet simply use a lock.
Personally I'd use a volatile Boolean:
private volatile bool m_LayoutSuspended = false;
public void SuspendLayout()
{
m_LayoutSuspended = true;
}
public void ResumeLayout()
{
m_LayoutSuspended = false;
}
public bool IsLayoutSuspended
{
get { return m_LayoutSuspended; }
}
Then again, as I've recently acknowledged elsewhere, volatile doesn't mean quite what I thought it did. I suspect this is okay though :)
Even if you stick with Interlocked, I'd change it to an int... there's no need to make 32 bit systems potentially struggle to make a 64 bit write atomic when they can do it easily with 32 bits...

Categories