C# threading - Lock Object - c#

I am trying to lock a "boxed" object in a c# app, is this not possible?
class t
{
System.Object t_x = new object();
public t(int p)
{
t_x = p;
}
public void w()
{
lock (t_x)
{
for (int i = 0; i < 4; i++)
{
{
t_x = ((int)t_x) + 1;
Console.WriteLine(t_x);
Thread.Sleep(1000);
}
}
}
}
}
In another class I can start 2 threads:
Thread b1 = new Thread(new ThreadStart(t1.w));
b1.Start();
Thread b2 = new Thread(new ThreadStart(t1.w));
b2.Start();
However the portion is not locked.
When I lock an arbitrary object (i.e. one created and not modified as object a=new object()) it locks well.
Is boxing operation somehow "depromotes" my Object??

No, you can't do this - the lock block is shorthand for the following:
try(Monitor.Enter(lockObject))
{
//critical section
}
finally
{
Monitor.Exit(lockObject)
}
The documentation for Monitor.Enter states, "Use Monitor to lock objects (that is, reference types), not value types. When you pass a value type variable to Enter, it is boxed as an object. If you pass the same variable to Enter again, it is boxed as a separate object, and the thread does not block"

You need to create a separate lock object. The problem is that you re-assign t_x inside the loop. Assuming thread b1 gets inside the loop before b2 gets to the lock statement, b2 will be allowed inside the lock statement because, by that time, t_x will be a new object that does not have a lock on it.

The lock (t_x) call boxes an integer as a temporary object. Each call to lock(t_x) creates a New object and locking is useless.
(Lock expects an object and creates a NEW temporary object from the integer)
Just create a seperate lock object like said above by Femaref.

You have to use an extra object for the lock
object lockObj = new object();
public void foo()
{
lock(lockObj)
{
//do stuff here
}
}

If you really want (need?) to lock on the object, you can use a kind of wrapper :
public class IntWrapper
{
public int Value{get;set;}
}
Or if you need to stay more abstract :
public class ObjectWrapper
{
public Object Value { get;set; }
}

If you want to recognise when the data is loaded and also if the use tries to use it before then, you can do something like this:
Have a boolean flag like you mention, but use a separate object to lock before accessing it to prevent cross-thread race conditions.
When the user tries to use the data, if it is not loaded (check the variable) you can add another event handler to the worker RunWorkerCompleted event, that will immediately do what the user wants when the data is loaded.
Example:
public class MyClass
{
private bool dataIsReady = false;
private object locker = new object();
BackgroundWorker worker;
public void Begin()
{
worker = new BackgroundWorker();
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
}
public void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lock (locker)
{
dataIsReady = true;
}
}
public void UseTriesToUseData()
{
lock (locker)
{
if (dataIsReady)
{
DoStuff();
}
else
{
this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(DoStuffCaller);
}
}
}
private void DoStuff()
{
// Do stuff with data.
}
private void DoStuffCaller(object sender, RunWorkerCompletedEventArgs e)
{
this.DoStuff();
}
}

Related

c# Object synchronisation error is thrown when calling Monitor.Pulse()

I'm trying to sync between two threads in my GUI system.
The main task of the system initialising two synchronisation objects and running two threads:
private FetcherAPI fetcherAPI { get; set; }
private FileReader fileReader { get; set; }
private object readerLocker;
private object writerLocker;
public Form1() {
InitializeComponent();
this.fetcherAPI = new FetcherAPI();
this.fileReader = new FileReader();
readerLocker = new object();
writerLocker = new object();
new Thread(() => {
this.fileReader.run(readerLocker);
});
new Thread(() => {
this.fixerAPI.run(writerLocker, readerLocker);
});
}
private void button1_Click(object sender, EventArgs e) {
Monitor.Pulse(writerLocker);
}
Reader Thread:
public void run(object readerLocker) {
while(true) {
Monitor.Wait(readerLocker);
readDataFromFileAndPresent();
}
}
Writer Thread:
public void run(object writerLocker, object readerLocker) {
while(true) {
Monitor.Wait(writerLocker);
fetchCurrency();
Monitor.Pulse(readerLocker);
Monitor.Wait(readerLocker);
}
}
When pressing the button I'm getting the following error:
object synchronization method was called from an unsynchronized block of code
What am I doing wrong?
Both Wait and Pulse can only be called if you already have the lock, i.e. you're inside a lock statement, or you've successfully used Monitor.Enter to acquire the lock. You haven't done either of those things, so : indeed, it won't work. The simplest fix would be to add a lock(writerLocker).

Avoid starting new thread with lock

Is this possible to lock method for one thread and force another to go futher rather than waiting until first thread finish? Can this problem be resolved with static thread or some proper pattern with one instance of mendtioned below service.
For presentation purposes, it can be done with static boolen like below.
public class SomeService
{
private readonly IRepository _repo;
public SomeService(IRepository repo)
{
_repo = repo;
}
private Thread threadOne;
public static bool isLocked { get; set; }
public void StartSomeMethod()
{
if(!isLocked)
{
threadOne = new Thread(SomeMethod);
isLocked = true;
}
}
public void SomeMethod()
{
while(true)
{
lots of time
}
...
isLocked = false;
}
}
I want to avoid situation when user clicked, by accident, two times to start and accidentailly second thread starts immediatelly after first finished.
You can use lock :)
object locker = new object();
void MethodToLockForAThread()
{
lock(locker)
{
//put method body here
}
}
Now the result will be that when this method is called by a thread (any thread) it puts something like flag at the beginning of lock: "STOP! You are not allowed to go any further, you must wait!" Like red light on crossroads.
When thread that called this method first, levaes the scope, then at the beginning of the scope this "red light" changes into green.
If you want to not call the method when it is already called by another thread, the only way to do this is by using bool value. For example:
object locker = new object();
bool canAccess = true;
void MethodToLockForAThread()
{
if(!canAccess)
return;
lock(locker)
{
if(!canAccess)
return;
canAccess = false;
//put method body here
canAccess = true;
}
}
Other check of canAccess in lock scope is because of what has been told on comments. No it's really thread safe. This is kind of protection that is advisible in thread safe singleton.
EDIT
After some discussion with mjwills I have to change my mind and turn more into Monitor.TryEnter. You can use it like that:
object locker = new object();
void ThreadMethod()
{
if(Monitor.TryEnter(locker, TimeSpan.FromMiliseconds(1))
{
try
{
//do the thread code
}
finally
{
Monitor.Exit(locker);
}
} else
return; //means that the lock has not been aquired
}
Now, lock could not be aquired because of some exception or because some other thread has already acuired it. In second parameter you can pass the time that a thread will wait to acquire a lock. I gave here short time because you don't want the other thread to do the job, when first is doing it.
So this solution seems the best.
When the other thread could not acquire the lock, it will go further instead of waiting (well it will wait for 1 milisecond).
Since lock is a language-specific wrapper around Monitor class, you need Monitor.TryEnter:
public class SomeService
{
private readonly object lockObject = new object();
public void StartSomeMethod()
{
if (Monitor.TryEnter(lockObject))
{
// start new thread
}
}
public void SomeMethod()
{
try
{
// ...
}
finally
{
Monitor.Exit(lockObject);
}
}
}
You can use a AutoResetEvent instead of your isLocked flag.
AutoResetEvent autoResetEvent = new AutoResetEvent(true);
public void StartSomeMethod()
{
if(autoResetEvent.WaitOne(0))
{
//start thread
}
}
public void SomeMethod()
{
try
{
//Do your work
}
finally
{
autoResetEvent.Set();
}
}

How to make a slightly modified AutoResetEvent class?

I need a synchronizing class that behaves exactly like the AutoResetEvent class, but with one minor exception:
A call to the Set() method must release all waiting threads, and not just one.
How can I construct such a class? I am simply out of ideas?
Martin.
So you have multiple threads doing a .WaitOne() and you want to release them?
Use the ManualResetEvent class and all the waiting threads should release...
Thank you very much for all your thougts and inputs which I have read with great interest. I did some more searching here on Stackoverflow, and suddenly I found this, whcih turned out to be just what I was looking for. By cutting it down to just the two methods I need, I ended up with this small class:
public sealed class Signaller
{
public void PulseAll()
{
lock (_lock)
{
Monitor.PulseAll(_lock);
}
}
public bool Wait(TimeSpan maxWaitTime)
{
lock (_lock)
{
return Monitor.Wait(_lock, maxWaitTime);
}
}
private readonly object _lock = new object();
}
and it does excactly what it should! I'm amazed that a solution could be that simple, and I love such simplicity. I'ts beautiful. Thank you, Matthew Watson!
Martin.
Two things you might try.
Using a Barrier object add conditionally adding threads too it and signaling them.
The other might be to use a publisher subscriber setup like in RX. Each thread waits on an object that it passes to a collection. When you want to call 'set' loop over a snapshot of it calling set on each member.
Or you could try bears.
If the event is being referenced by all threads in a common field or property, you could replace the common field or property with a new non-signaled event and then signal the old one. It has some cost to it since you'll be regularly creating new synchronization objects, but it would work. Here's an example of how I would do that:
public static class Example
{
private static volatile bool stopRunning;
private static ReleasingAutoResetEvent myEvent;
public static void RunExample()
{
using (Example.myEvent = new ReleasingAutoResetEvent())
{
WaitCallback work = new WaitCallback(WaitThread);
for (int i = 0; i < 5; ++i)
{
ThreadPool.QueueUserWorkItem(work, i.ToString());
}
Thread.Sleep(500);
for (int i = 0; i < 3; ++i)
{
Example.myEvent.Set();
Thread.Sleep(5000);
}
Example.stopRunning = true;
Example.myEvent.Set();
}
}
private static void WaitThread(object state)
{
while (!Example.stopRunning)
{
Example.myEvent.WaitOne();
Console.WriteLine("Thread {0} is released!", state);
}
}
}
public sealed class ReleasingAutoResetEvent : IDisposable
{
private volatile ManualResetEvent manualResetEvent = new ManualResetEvent(false);
public void Set()
{
ManualResetEvent eventToSet = this.manualResetEvent;
this.manualResetEvent = new ManualResetEvent(false);
eventToSet.Set();
eventToSet.Dispose();
}
public bool WaitOne()
{
return this.manualResetEvent.WaitOne();
}
public bool WaitOne(int millisecondsTimeout)
{
return this.manualResetEvent.WaitOne(millisecondsTimeout);
}
public bool WaitOne(TimeSpan timeout)
{
return this.manualResetEvent.WaitOne(timeout);
}
public void Dispose()
{
this.manualResetEvent.Dispose();
}
}
Another more lightweight solution you could try that uses the Monitor class to lock and unlock objects is below. However, I'm not as happy with the cleanup story for this version of ReleasingAutoResetEvent since Monitor may hold a reference to it and keep it alive indefinitely if it is not properly disposed.
There are a few limitations/gotchas with this implementation. First, the thread that creates this object will be the only one that will be able to signal it with a call to Set; other threads that attempt to do the same thing will receive a SynchronizationLockException. Second, the thread that created it will never be able to wait on it successfully since it already owns the lock. This will only be an effective solution if you have exactly one controlling thread and several other waiting threads.
public static class Example
{
private static volatile bool stopRunning;
private static ReleasingAutoResetEvent myEvent;
public static void RunExample()
{
using (Example.myEvent = new ReleasingAutoResetEvent())
{
WaitCallback work = new WaitCallback(WaitThread);
for (int i = 0; i < 5; ++i)
{
ThreadPool.QueueUserWorkItem(work, i.ToString());
}
Thread.Sleep(500);
for (int i = 0; i < 3; ++i)
{
Example.myEvent.Set();
Thread.Sleep(5000);
}
Example.stopRunning = true;
Example.myEvent.Set();
}
}
private static void WaitThread(object state)
{
while (!Example.stopRunning)
{
Example.myEvent.WaitOne();
Console.WriteLine("Thread {0} is released!", state);
}
}
}
public sealed class ReleasingAutoResetEvent : IDisposable
{
private volatile object lockObject = new object();
public ReleasingAutoResetEvent()
{
Monitor.Enter(this.lockObject);
}
public void Set()
{
object objectToSignal = this.lockObject;
object objectToLock = new object();
Monitor.Enter(objectToLock);
this.lockObject = objectToLock;
Monitor.Exit(objectToSignal);
}
public void WaitOne()
{
object objectToMonitor = this.lockObject;
Monitor.Enter(objectToMonitor);
Monitor.Exit(objectToMonitor);
}
public bool WaitOne(int millisecondsTimeout)
{
object objectToMonitor = this.lockObject;
bool succeeded = Monitor.TryEnter(objectToMonitor, millisecondsTimeout);
if (succeeded)
{
Monitor.Exit(objectToMonitor);
}
return succeeded;
}
public bool WaitOne(TimeSpan timeout)
{
object objectToMonitor = this.lockObject;
bool succeeded = Monitor.TryEnter(objectToMonitor, timeout);
if (succeeded)
{
Monitor.Exit(objectToMonitor);
}
return succeeded;
}
public void Dispose()
{
Monitor.Exit(this.lockObject);
}
}

Do I need to use locks when simply assigning variables?

When multithreading I know that I need to lock variables if doing things like adding and item to a list etc or I would get a cross thread exception. But do I need to lock them when just assigning variables? I don't mind about if a thread getting an old instance of the variable - I just don't want it to error. Here is an example of what I mean:
public void Run()
{
var thread1 = new Thread(new ThreadStart(Test));
var thread2 = new Thread(new ThreadStart(Test));
thread1.Start();
thread2.Start();
}
private static int _test;
private void Test()
{
while (true)
{
_test += 1;
}
}
If you're just assigning an int, then no. But here you're not just assigning. You're incrementing. So you need some kind of synchronization.
In you want to increment, use Interlocked.Increment:
Interlocked.Increment(ref _test);
Running the code should give you your answer... instead of while(true) write for(i=1;1<1e6;i++) , write the result to screen and run it.
You'll see it does not add up to 2e6, but rather something around 1.2e6. So yes, you need to lock if you want to get out 2e6.
Don't just hypothesize, after that always test and assert.
You have to remember the thread could also be looking at a stale copy, by locking you assure that the version of the variable you are looking at is being refreshed
When I first started coding and thought that maybe I don't need the freshest copy of the variable I would get stuck in infinite loops because I assume the variable would be updated eventually, but if the variable was cached then it would never update
I included examples with brief descriptions, don't worry about the way the thread is started, that is not relevant
private static bool _continueLoop = true;
private static readonly object _continueLoopLock = new object();
private static void StopLoop()
{
lock(_continueLoopLock)
_continueLoop = false;
}
private static void ThreadALoopWillGetStales()
{
while(_continueLoop)
{
//do stuff
//this is not guaranteed to end
}
}
private static void ThreadALoopEventuallyCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
doContinue = _continueLoop;
if(!doContinue)
break;
//do stuff
//this will sometimes result in a stale value
//but will eventually be correct
}
}
private static void ThreadALoopAlwaysCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
if(!_continueLoop)
break;
//do stuff
//this will always be correct
}
}
private static void ThreadALoopPossibleDeadlocked()
{
lock(_continueLoopLock)
while(_continueLoop)
{
//if you only modify "_continueLoop"
//after Acquiring "_continueLoopLock"
//this will cause a deadlock
}
}
private static void StartThreadALoop()
{
ThreadPool.QueueUserWorkItem ((o)=>{ThreadALoopWillGetStales();});
}
private static void StartEndTheLoop()
{
ThreadPool.QueueUserWorkItem((o)=>
{
//do stuff
StopLoop();
});
}
public static void Main(string[] args)
{
StartThreadALoop();
StartEndTheLoop();
}
when you start the loop there is a chance that you will continue to get a stale copy of the variable, that is why you do need some sort of synchronization when accessing a across multiple threads

C# using lock practice

I have critical section in my application which contains a lot of code:
which is better way to locking access in threadMethod:
A) lock all block:
private object locker = new object();
private void threadMethod()
{
while(true)
{
lock(locker)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
B) Use additional locked access member canWork:
private static object locker = new object();
private bool canWork;
private bool CanWork
{
get { lock(locker) { return this.canWork; } }
set { lock(locker) { this.canWork = value; } }
}
private void threadMethod()
{
while(true)
{
if(CanWork)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
and somewhere in code
CanWork = false;
Neither is particularly good.
The first has the disadvantage that you hold the lock for a long time.
The second has the disadvantage that the state can change after you check it.
Instead try to pass immutable arguments to your method (for example a copy of the data). You will probably still need to lock for constructing the arguments and for collecting the results but this is hopefully a much shorter period of time.
The second approach will likely lead to race conditions. Can your "a lot of code" be separated in several critical/non critical chunks?
I would use the Monitor instead. Plus do you really want while(true) because this will repeat forever?
private object syncObject = new object();
private void threadMethod()
{
bool tryToRun = true;
while(tryToRun)
{
if(Monitor.TryEnter(syncObject))
{
tryToRun = false;
// do work - a lot of code here
Monitor.Exit(syncObject);
}
else
{
Thread.Sleep(2000); // Possibly knock this up the how long you expect the lock to be held for.
}
}
}
est link:
http://msdn.microsoft.com/en-us/magazine/cc188793.aspx#fig7
Best usage is
- declare a new private sync object
- use "lock(synObject) { code here ... }

Categories