Problem: I'm using a C# lock statement to protect my variable '_NextId' when I increment it and assign its new value. I don't want any other threads interrupting and snagging the value until the increment has completed.
Unfortunately, it doesn't seem to work, because I'm getting duplicates when I run it in a parallel loop. This indicates to me that another thread has managed to sneak into my protected code.
Here's the code that doesn't work as expected:
public class Widget {
private static int _NextId;
private object _LockToken = new object();
public Widget() {
//I expected this lock to prevent any other thread from assigning its ID until we have
//completed incrementing the member variable
lock (_LockToken) {
ID = ++_NextId;
}
}
public int ID { get; private set; }
}
Here's a link to DotNetFiddle that proves duplicates are created. I interpret that result as indicating the lock doesn't work the way I expected. The DotNet fiddle runs the code above in a parallel loop and then counts how many duplicate IDs were created. If you run it, it will print a message displaying the duplicate count.
In your code, a different _LockToken is being created for every widget.
Try adding a static modifier to the _LockToken, so all instances of the Widget class refer to the same "lock token".
You should declare the _LockToken variable as static to ensure the locks are taken against the same object.
Related
As working on multi-threaded application, I have once scenario where I need to assign value to static field. I want to use the latest value of static field in all rest of the threads.
Code is seems like below:
Main() Method:
for (var i = 1; i <= 50; i++)
{
ProcessEmployee processEmployee = new ProcessEmployee();
Thread thread = new Thread(processEmployee.Process);
thread.Start(i);
}
public class ProcessEmployee
{
public void Process(object s)
{
// Sometimes I get value 0 even if the value set to 1 by other thread.
// Want to resolve this issue.
if (StaticContainer.LastValue == 0)
{
Console.WriteLine("Last value is 0");
}
if (Convert.ToInt32(s) == 5)
{
StaticContainer.LastValue = 1;
Console.WriteLine("Last Value is set to 1");
}
// Expectation: want to get last value = 1 in all rest of the threads.
Console.WriteLine(StaticContainer.LastValue);
}
}
public static class StaticContainer
{
private static int lastValue = 0;
public static int LastValue
{
get
{
return lastValue;
}
set
{
lastValue = value;
}
}
}
Question:
Basically, I want to know that once I set specific value to static field by any thread, I want to get the same value (latest value set by another thread) in rest of the threads always.
Please do give me any idea on this.
Thanks in advance!
Basically, I want to know that once I set specific value to static field by any thread, I want to get the same value (latest value set by another thread) in rest of the threads always.
It sounds like you're basically missing a memory barrier. You could work this out with explicit barriers but no locks - or you could just go for the brute-force lock approach, or you could use Interlocked:
private static int lastValue;
public int LastValue
{
// This won't actually change the value - basically if the value *was* 0,
// it gets set to 0 (no change). If the value *wasn't* 0, it doesn't get
// changed either.
get { return Interlocked.CompareExchange(ref lastValue, 0, 0); }
// This will definitely change the value - we ignore the return value, because
// we don't need it.
set { Interlocked.Exchange(ref lastValue, value); }
}
You could use volatile as suggested by newStackExchangeInstance in comments - but I'm never actually sure I fully understand exactly what it means, and I strongly suspect it doesn't mean what most people think it means, or indeed what the MSDN documentation states. You may want to read Joe Duffy's blog post on it (and this one too) for a bit more background.
If two different threads may access the same field/variable and at least one of them will be writing, you need to use some sort of locking. For primitive types use the Interlocked class.
I'm using a switch as a state manager for my XNA game. The switch is a part of main update method, so it's run every frame. Sometimes I need to set a timer value and it should only be set once per method call. There are multiple methods that set the timer per case, so it can't use the current and previous state numbers to check if it's ok to overwrite previous time.
case "state 34": {
SetTime(theTime); // should run only once
// other things
if (TheTimeisRight(time)) // runs every call
{
SetTime(theTime); // should run only once
if (TheTimeisRight(time))
{ /* some methods */ }
}
break; }
How can I make this work, or is there a better way to do this without going outside the switch? (changing SetTime method is ok, but I wouldn't like to clutter up the switch with additional code)
Another method: Introduce a wrapper around the method you want to call:
public sealed class RunOnceAction
{
private readonly Action F;
private bool hasRun;
public RunOnceAction(Action f)
{
F = f;
}
public void run()
{
if (hasRun) return;
F();
hasRun = true;
}
}
Then create var setTimeOnce = new RunOnceAction(() => SetTime(theTime)); before the switch statement, and call there as setTimeOnce.run(). Adjust for parameters/return values as necessary.
If you don't want to mess with boolean variables ala hasSetTimeAlready, you can always introduce another state that calls the method, then proceeds to the original state.
Put the call outside the loop.
You might need a separate conditional statement to determine whether it should run at all, but that's got to be infinitely better than trying to use flags and/or various other smelly-code approaches to control repetitions of the call.
Edit:
here is what I mean by putting it in one place outside of the switch:
if (someCondition && someOtherCondition && yetAnotherCondition)
setTime(theTime); // just one call, in one place, gets executed once
switch(someValue)
{
case "state 34": {
//SetTime(theTime); // no longer necessary
// other things
if (TheTimeisRight(time)) // runs every call
{
//SetTime(theTime); // no longer necessary
if (TheTimeisRight(time))
{ /* some methods */ }
}
break;
...etc...
}
A word of advice: use an enumeration for your switch value rather than a string.
To be brutally honest, this is about as much as anyone can realistically help you with this without seeing a more complete code sample (I think the sample you gave us is somewhat contrived and not quite accurate to what you have?). Chances are that the best way to get round this problem is to deconstruct the switch statement and start again because either maintaining a state machine is not the best way to handle this situation or you need to introduce some other states.
I have resorted to using HashSet<int> to check if the current SetTime(time, num) method has not been called before with if (!hashSet.Contains(num)).
void SetTime(int time, int num)
{
if (!hashSet.Contains(num))
{
theTime = time;
hashSet.Add(num);
}
}
Sure doesn't look too cool, but works and it doesn't damage method call too much (visually), so the switch's readability is saved.
1) I'm working on a project and I saw this piece of code, I don't understand what is the point of the Monitor.Lock statement. Can someone explain what its trying to do?
2) the postscript underscroll in the parameter name is really annoying, anyone else seen this naming convention?
public class FieldsChangeableHelper<T> : IFieldsChangeable<T>
{
object _lock;
int _lockCount;
FieldChanges<T> _changes;
public FieldsChangeableHelper()
{
_lock = new object();
_lockCount = 0;
}
public void AddChange(T field_, object oldValue_)
{
if (_changes == null)
_changes = new FieldChanges<T>(field_, oldValue_);
else
_changes.AddChange(field_, oldValue_);
if (RaiseEvent(_changes))
_changes = null;
}
#region IFieldsChangeable Members
public void BeginUpdate()
{
if (System.Threading.Interlocked.Increment(ref _lockCount) == 1)
Monitor.Enter(_lock);
}
public void EndUpdate()
{
if (System.Threading.Interlocked.Decrement(ref _lockCount) == 0)
{
FieldChanges<T> changes = _changes;
_changes = null;
Monitor.Exit(_lock);
RaiseEvent(changes);
}
}
protected bool RaiseEvent(FieldChanges<T> changes_)
{
if (_lockCount == 0 && Changed != null && changes_ != null)
{
Changed(this, changes_);
return true;
}
return false;
}
public event FieldsChanged<T> Changed;
#endregion
}
Monitor.Lock locks the portion of code when multiple thread tries to execute the same piece in parallel. It is made to ensure that only 1 guy is altering/executing the context. Look at the MSDN.
Although its best practice that the locking object is always static, but in your case it is not. Which might pose some problem if your instantiating multiple objects on an open type.
Note one thing, in generics static on open T is different for different type, i.e static member in an Open Type class in your case is different for T i.e DateTime, string, etc.
In csharp, private members of a type are usually named with prefixed _
The way i read it: BeginUpdate() ensures that the current thread calling has exclusive access to the instance and that change events practically will be batched and raised once EndUpdate is called. The author wanted to deal with recursion by itself (e.g. calling BeginUpdate() on the same thread multiple times) and a mechanism to batch UpdateEvents untill after the lock has been released. Because, there is a potential deadlock when raising Events when you still have a lock on yourself. event subscribers might want to access your members and therefore have to lock the sender instance which is already locked.
The whole conditional locking is not required (if my analyses is correct ofcourse) since locks based on the Monitor class are recursive and counted.
There is another problem with the locking mechanism, that is: currently when one thread holds a lock. The second thread wont even wait for the lock but will simply continue without a lock since the lock is conditional! this seems like a big bug!
Regarding the naming convention. I use it myself for a way of differentiating privates from parameters and locals. Its a preference which many C# coding conventions recommend. This helps in a case like this:
void Method(int number)
{
// no need to refer to this since:
//this.number = number;
// can be replaced with
_number = number;
}
I'm working on a program but an issue i was faced to keep me worried.I'm kind of novice and i'm building this program for a competition.The code where the problem lies is like following :
class Blabla : Usercontrol
{
public List<string> mainList;
public Blabla()
{
mainList = new List<string>();
something.DownloadStringCompleted += new DownloadStringCompletedEventHandler(xx_DownloadStringCompleted);
}
void xx_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
List<string> abc = SomeMethod(e.Result);
mainList = abc;
}
}
I try it.Even though "abc" variable has the value i want , mainList remains empty.I don't know why and how to make it work.That's why i need some hand.Thank you.
Variable abc has the value you want UNTIL you get out of your event handler, probably, when it gets deleted because it uses e.Result directly.
Familiarize yourself with .Clone() method and IClonable interface, and try creating a COPY of the list that is in question, not the reference.
If abc is a list, mainList will be set to the same list. You don't have to clone the list, it should stay active because there is a reference to it, and therefore it doesn't get garbage collected.
When you said that mainList was empty, did you look at it in the debugger immediately after setting it in the xx_DownloadStringCompleted method? Or are you looking at it somewhere else in your program?
I would guess that this is a threading issue. Does your event handler get called from a different thread? If so, you would need to add some synchronization logic in order to guarantee that mainList is available to your other thread.
consider the following code that is executed in every instantiation of a certain class:
private void StartUpdateThread()
{
runUpdateThread = true;
Thread thread = new Thread(new ThreadStart(UpdateUsages));
thread.Priority = ThreadPriority.BelowNormal;
thread.Start();
}
public void UpdateUsages()
{
DateTime updateDateTime = DateTime.Now;
while (runUpdateThread)
{
if (updateDateTime <= DateTime.Now)
{
_cpuUsage.Add(DateTime.Now, GetCPUUsage());
if (_cpuUsage.Count == 61)
_cpuUsage.Remove(_cpuUsage.ElementAt(0).Key);
_ramUsage.Add(DateTime.Now, GetRamUsage());
if (_ramUsage.Count == 61)
_ramUsage.Remove(_ramUsage.ElementAt(0).Key);
updateDateTime = DateTime.Now.AddSeconds(15);
}
Thread.Sleep(15000);
}
}
After adding 2 or 3 values to each Dictionary it throws "an element with the same key already exists in the dictionary". This should be impossible since i'm doing Sleep after each loop.
I've tried, unsuccessfully, to prevent this problem by adding the updateDateTime variable.
I'm running out of ideas. Can anyone help me or explain me how this can happen?
Thanks
Are either _cpuUsage or _ramUsage static by any chance? Or perhaps you've assigned the same value to both of them? If you could give us a short but complete program which demonstrates the problem, it would make things a lot clearer.
On a side note, you seem to be hoping that your usage of ElementAt(0) will remove the earliest entry from the dictionary, but there's no guarantee of that.
From what you're doing, it looks like you'd be better off with a LinkedList<Tuple<DateTime, long>> or similar.