2

I'm trying to teach myself about threads in C#, and I've run into a problem. Lets say that this is my code:

class MyClass
{
    public Queue variable;
    internal MyClass()
    {
        variable = new Queue<int>();
        variable.Enqueue(1);
        Thread thread = new Thread(new ThreadStart(DoSomething));
        thread.IsBackground = true;
        thread.Start();
    }
    public void DoSomething()
    {
        int i = variable.Dequeue();
        MessageBox.Show(i);
    }
}

Upon execution I get an exception saying that the queue is empty when I try to dequeue. Debugging shows that the queue is empty within the context of the thread, but not in the larger class. I assume that C# creates thread-local objects for certain things (but not all, if I were to make an int member variable, I could get its value within the thread without any problems) I know java does similiar things, and the way around it is to declare the member variable as "volatile" or something like that. C# has a similiar construct, but I don't think its what I'm looking for (or at least, I used it and it didn't help...) How would I declare a member variable in C# such that any threads created by the class also can access it? (I'd also really like to understand this stuff better, so links to relevant material would be greatly appreciated)

Hamlet Hakobyan
  • 32,965
  • 6
  • 52
  • 68
redsoxfantom
  • 918
  • 1
  • 14
  • 29

2 Answers2

1
class MyClass {
    public Queue variable; 
    internal MyClass() {
        variable = new Queue(); 
        variable.Enqueue(1); 
        Thread thread = new Thread(new ThreadStart(DoSomething)); 
        thread.IsBackground = true; 
        thread.Start(); 
    } 
    public void DoSomething() { 
        int i = (int)(variable.Dequeue()); //cast required here
        //MessageBox may not play nice from non-ui thread
        Console.WriteLine(i); 
    } 
}

works fine with only the smallest edit. The queue is visible from the thread. It's not clear how you reached a different conclusion.

You might consider using a generic Queue<int> to avoid the boxing/unboxing associated with storing value types in non-generic collections.

Better yet, you could avoid a whole bunch of noisy thread-synchronization too by using ConcurrentQueue<T>, seeing as you're sharing this queue between threads.

Community
  • 1
  • 1
spender
  • 117,338
  • 33
  • 229
  • 351
0

I think you should change these two lines and it should work.

public Queue<int> variable;

MessageBox.Show(i.ToString());
yazan
  • 600
  • 7
  • 12