views:

61

answers:

1

I am running four threads that gets and sets the same property. When i uses breakpoint then it gives me result as expected but when i runs it directly it gives me last updated result.

Here is my code

int Port { get; set; }
Thread[] tMain= new Thread[4];

 public void btnListen_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 4; i++)
            {
                tMain[i] = new Thread(Connect);
                tMain[i].IsBackground = true;
                tMain[i].Start(8000+i);
            }
        }


 public void Connect(object _port)
        {
            try
            {
                lock ((object)Port)
                {
                    Port = (int)_port;
                }
                IPEndPoint ie = new IPEndPoint(IPAddress.Any, Port);
                Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                listenSock.Bind(ie);
                listenSock.Listen(100);
                Thread tListen = new Thread(() => StartListening(listenSock, Port));
                tListen.IsBackground = true;
                tListen.Start();
            }
            catch (SocketException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

public void StartListening(Socket _socket, int port)
        {
            Socket tempSock,listenerSocket=(Socket)_socket;
            MessageBox.Show("Thread Started"+port.ToString());
            while (true)
            {
                MessageBox.Show("Waiting For Connection");
                tempSock = listenerSocket.Accept();

                Thread tInner = new Thread(ProcessMessages);
                tInner.IsBackground = true;
                tInner.Start(tempSock);
            }
        }

Now what I see over here is when the code is executed i gets 8003 in all the message boxes. That's might be because first 3 thread could not modify the property in the meantime when it was accessed . How to get a lock in this case.

+2  A: 

This code definitely needs some refactoring for a start - too many threads being spanwed, and all in a very narrow context!

Short answer:

The problem boils down to the fact that Connect function is not called at the times (or even order) you expect it to be, but rather only when the loop is finished.

Long answer:

This is fairly typical scenario of concurrency issues when trying to use instance-scoped variables/properties within functions. As far as I can tell, the issue with not getting the desired value for Port is nothing directly to do with locking per se. (It may be solved that way, but not very gracefully and not in the way you probably think.) Ultimately you cannot control how blocks of time are allocated to different threads on the processor level, so you don't know which functions get executed in what order. You also seem to be mixing principles of stateful and stateless (functional) design, which is bound to get you into trouble. Stick to one - preferably the latter in this case - and you'll have much more success.

So I hope I'm being harsh to be kind here in saying that it would likely be beneficial to read up a bit on multithreading - it's a hugely complex topic - and practice some of the common principles. Good luck!

Noldorin
@Noldorin: There is nothing like getting harsh i feel. it is a pleasure for me to know about these. Although this was my first program on Socket creation and Multithreading. And as u told just now that threads are being called after looping terminates so it was a new hidden feature of thread to me. Although I have 2-3 solutions over here to use. Either by using collections or by using static value of port. What other things can be done and if I think of taking a lock then how would i be taking it. Will it be possible here in this scenario to get a lock. As I think lock is not possible
Shantanu Gupta
As explained by you that each thread will start after loop terminates.
Shantanu Gupta
The most obvious solution is probably just to get rid of your `Port` class variable - don't quite see the need for it anyway. Do everything functionally, and pass things as parameters.
Noldorin
@Noldorin: yes, initially i didn't used this property but when every thing got right then i introduced it and there after I saw this problem. For this particular case i wanted to know how could it be solved- By taking locks, by setting thread priority, by suspending thread and if any other way too exists. It would be nice if you could provide an eg of these. I was able to set lock on property by converting Port as an object but i think it didn;t worked.
Shantanu Gupta
Also, I recommend you read into asynchronous sockets - they make your life easier in many cases, since you work with callbacks rather than threads. Certainly, the ProcessMessages thread is unnecessary, just call that synchronously as a method.
Noldorin
I searched a lot for asynchronous socket article, but i couldn't get any good article yet. Once I am done with sync socket I will be giong though that as well and also thanks for your precious time and support.
Shantanu Gupta
No problem... It may not explain everything, but these two MSDN articles should help: http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx and a demo: http://code.msdn.microsoft.com/NitoSockets
Noldorin
@Noldorin: So nice of you, Thx for the links. Will go though them once i clear my concepts with multithreading.
Shantanu Gupta