Hello, Newsgroupians:
I'm a little confused when it comes to threads in C#. Here's what I'm
trying to do...
I have a List<> containing a set of MyPoint(s)...
public struct MyPoint
{
int x;
int y;
int val;
}
class MyClass
{
List<MyPoint> m_list = new List<MyPoint>();
...
}
Now, in my main thread I'm going to populate the list. Assume the
following...
class MyClass
{
public MyClass()
{
for (int i = 0; i < 10; i++)
{
MyPoint pt = new MyPoint;
pt.x = <Some X>
pt.y = <Some Y>
// pt.val is changed in the thread
m_list.Add(pt);
}
}
...
}
Now, in the secondary thread, I am going to be changing .val
For simplicity, assume I do the following...
class MyClass
{
void SomeFunc()
{
Thread th = new Thread(new ThreadStart(this.ThreadFunc));
th.Start();
while (th.IsAlive) // Wait until the secondary thread is done
{
Thread.Sleep(1000);
}
for (int i = 0; i < m_list.Count; i++)
{
Console.WriteLine(m_list[i].val);
}
}
public void ThreadFunc()
{
Random r = new Random();
for (int i = 0; i < this.m_list.Count; i++)
{
MyPoint pt = this.m_list[i];
pt.val = r.Next();
}
...
}
}
Yet, even after waiting for the secondary thread to end, the .val for each
MyPoint in the List<> is always zero. I don't understand why it isn't
changing. I've tried setting some variables to static; this didn't work.
Overall, what do I need to do to make it so the secondary thread can write
to the values in the List<> and have the main thread read these values once
the thread has ended? Thank you.
Trecius
Marc Gravell - 30 Nov 2007 15:34 GMT
The answer is that MyPoint is a struct; it has value-type semantics.
Every time you get it from the list you get a *different* copy.
Aside: there isn't any locking, but you've guarded against this OK
because the two threads don't run at the same time - but be aware that
there are some register issues which might stop loops exiting -
and .Join() would be more efficient anyway.
But more importantly:
th.Start();
while (th.IsAlive) // Wait until the secondary thread is done
{
Thread.Sleep(1000);
}
Why start a thread, just to wait for it to end... run the code
directly ;-p
Marc
Marc Gravell - 30 Nov 2007 15:38 GMT
And can I point out that I already told you this?
http://groups.google.co.uk/group/microsoft.public.dotnet.languages.csharp/browse
_thread/thread/6479abc1c12a8bba
Marc
Trecius - 30 Nov 2007 15:41 GMT
Mr. Gravell:
So should my struct be a class?
Trecius
> The answer is that MyPoint is a struct; it has value-type semantics.
> Every time you get it from the list you get a *different* copy.
[quoted text clipped - 16 lines]
>
> Marc
Bill Butler - 30 Nov 2007 16:15 GMT
Yes,
A good rule of thumb is to ALWAYS use classes in your design.
structs are not the same as in C++.
Make sure that you fully understand all of the subtle ramifications of
using structs in your design before attempting to do so. Most of the
time you will find that classes are a far better choice.
Bill
> Mr. Gravell:
>
[quoted text clipped - 23 lines]
>>
>> Marc
Ignacio Machin ( .NET/ C# MVP ) - 30 Nov 2007 15:42 GMT
Hi,
Just change MyPoint from a struct to a class and run the test again.
Take a look at Jon Skeet's comment regarding value vs reference types

Signature
Ignacio Machin
http://www.laceupsolutions.com
Mobile & warehouse Solutions.
> Hello, Newsgroupians:
>
[quoted text clipped - 78 lines]
>
> Trecius
Rene - 30 Nov 2007 20:06 GMT
Since several people already answered the question, the other question would
be, why won't the compiler issue a warning such as:
The private field 'pt' is assigned but its value is never used.
And then add the squiggly line underneath the variable to make this very
obvious. This would be nice since people always run into scenarios like
this.
I mean, I realize that the "ThreadFunc()" function has the "pt.val =
r.Next()" line that uses the 'pt' variable but there is only assignments to
it right? the "ThreadFunc()" never really extracts a value from 'pt' so my
guess is that the warning would hold true.
No? Yes? Maybe?
> Hello, Newsgroupians:
>
[quoted text clipped - 78 lines]
>
> Trecius