Thread View: borland.public.cppbuilder.internet.socket
6 messages
6 total messages
Started by Mark Atkin
Thu, 20 Apr 2006 20:25
Using TClientSocket in multi-threaded app
Author: Mark Atkin
Date: Thu, 20 Apr 2006 20:25
Date: Thu, 20 Apr 2006 20:25
40 lines
3147 bytes
3147 bytes
I have a multi-threaded application where each thread uses TClientSocket to communicate to a device on the network. I start a new thread for each device that I need to talk to. My main form starts each of these threads, and when a timer on the main form reaches 0, a flag is set in each thread to tell the thead that it is time to talk to it's device. The next time the thread checks it's status, the thread calls new TClientSocket to allocate a new socket connection to use for the communication, retrieves the data, then deletes it's instance of TClientSocket. Everything seems to work fine on my computer. When I tried it on a client's computer, I began getting AVs when the thread was calling new TClientSocket. I was creating my instances of TClientSocket as follows: TClientSocket *sock = new TClientSocket(MainForm); where MainForm is the address of my form with the timer and the form that creates the threads. My theory as to why I would get AVs is that maybe all three threads are calling new TClientSocket(MainForm) almost simultaneously and basically, some method and/or property from my MainForm is being accessed by all three threads to add the TClientSocket component to the ComponentList array and increment the ComponentCount for the MainForm. I changed the socket instantiation to new TClientSocket(NULL) and the problem has gone away. This seems to agree with my theory, but it's just a theory. The biggest hole in my theory that I can see is that it doesn't really explain why it would work on my PC and not my clients. We are both running XPSP2 on P4s. It still could be a timing issue, but I would like to prove this theory somehow. Also, the only advantage that I can see to having MainForm being the owner of the TClientSocket is that if something unexpected occurs and the TClientSocket doesn't get deleted somehow, the MainForm will free up the memory when the form gets destroyed. This advantage is greatly decreased by the fact that the form is never destroyed until the program exits, in which case Windows is going to free up the memory anyway. Any thoughts, opinions, or additional theories (or even proofs with examples :P) on this would be greatly appreciated. Regards, Mark Atkin
Re: Using TClientSocket in multi-threaded app
Author: SF
Date: Wed, 26 Apr 2006 09:59
Date: Wed, 26 Apr 2006 09:59
48 lines
2475 bytes
2475 bytes
> TClientSocket *sock = new TClientSocket(MainForm); I always use TClientSocket *sock = new TClientSocket(NULL); to create client sockets inside a thread. You yourself noticed this is the right way. > My theory as to why I would get AVs is that maybe all three > threads are calling new TClientSocket(MainForm) almost > simultaneously and basically, I don't care about that. Why should MainForm be the owner of an object created inside a different thread? > The biggest hole in my theory that I can see is that it > doesn't really explain why it would work on my PC and not my > clients. That should be deeply checked, but again, you shouldn't care too much IMO. > It still could be a timing issue, Or another thousands of issues... > Also, the only advantage that I can see to having MainForm > being the owner of the TClientSocket is that if something > unexpected occurs and the TClientSocket doesn't get deleted > somehow, the MainForm will free up the memory when the form > gets destroyed. Not a big advantage. Almost a disadvantage under certain points of view. > This advantage is greatly decreased by the fact that the form > is never destroyed until the program exits, in which case > Windows is going to free up the memory anyway. Anyway, your thread should be strong enough to handle any possible problem and free the TClientSocket pointer by itself. Did you find anything more in the meantime? HTH, Stefano.
Re: Using TClientSocket in multi-threaded app
Author: Remy Lebeau (TeamB)
Date: Wed, 26 Apr 2006 17:14
Date: Wed, 26 Apr 2006 17:14
68 lines
3935 bytes
3935 bytes
"Mark Atkin" <matkin@windrock.com> wrote in message news:4447ee51$1@newsgroups.borland.com... > The next time the thread checks it's status, the thread calls new > TClientSocket to allocate a new socket connection to use for > the communication, retrieves the data, then deletes it's instance > of TClientSocket. A better approach would be to create the TClientSocket instance only once when the thread is created and then free the TClientSocket when the thread is being freed. You don't need to create a new TClientSocket instance over and over during the thread's lifetime. Just Connect/Disconnect it when needed. > When I tried it on a client's computer, I began getting AVs when > the thread was calling new TClientSocket. That is because of the way you are managing the TClientSocket. Keep reading... > I was creating my instances of TClientSocket as follows: > > TClientSocket *sock = new TClientSocket(MainForm); That is not thread-safe. You are telling the TClientSocket to be owned by a TForm that resides in another thread. All of the ownership management that the VCL does internally only works when used in a single thread. In this case, you should be using NULL instead to assign no owner to the TClientSocket at all. The thread manages the TClientSocket's lifetime, so there is no need to assign any owner anyway. > My theory as to why I would get AVs is that maybe all three threads > are calling new TClientSocket(MainForm) almost simultaneously and > basically, some method and/or property from my MainForm is being > accessed by all three threads to add the TClientSocket component to > the ComponentList array and increment the ComponentCount for the > MainForm. That is very likely, yes. Which is exactly why specifying an Owner is not thread-safe at all. > I changed the socket instantiation to new TClientSocket(NULL) and > the problem has gone away. There you go then. > The biggest hole in my theory that I can see is that it doesn't really > explain why it would work on my PC and not my clients. A fluke, nothing more. It is likely just a timing issue, which are very difficult to debug. Maybe your computer is slower then the client's computer and thus the problem doesn't show up as much on your machine since the main thread properties/members are not access quite as simultaneously. > Also, the only advantage that I can see to having MainForm being > the owner of the TClientSocket is that if something unexpected occurs > and the TClientSocket doesn't get deleted somehow, the MainForm > will free up the memory when the form gets destroyed. That is a very bad design when threads are involved. You should not be assigning ownership across threads. Each thread should own its own objects. If something goes bad and your main thread does not terminate the threads, the threads will still be running when the main thread frees the objects that the threads are using. Gambit
Re: Using TClientSocket in multi-threaded app
Author: Mark Atkin
Date: Wed, 26 Apr 2006 17:34
Date: Wed, 26 Apr 2006 17:34
69 lines
3183 bytes
3183 bytes
"SF" <invalid@NOSPAMinvalid.com> wrote in message news:<444f4499$2@newsgroups.borland.com>... > > TClientSocket *sock = new TClientSocket(MainForm); > > I always use > > TClientSocket *sock = new TClientSocket(NULL); > Me too, from now on ;) > to create client sockets inside a thread. You yourself noticed this is the > right way. > > > My theory as to why I would get AVs is that maybe all three threads are > > calling new TClientSocket(MainForm) almost simultaneously and basically, > > I don't care about that. Why should MainForm be the owner of an object > created inside a different thread? > When I first coded this, I didn't realize that NULL was a valid argument. I thought I had to supply a valid TComponent instance. I now know that's not the case. > > The biggest hole in my theory that I can see is that it doesn't really > > explain why it would work on my PC and not my clients. > > That should be deeply checked, but again, you shouldn't care too much IMO. > I've got the same opinion, now. Who cares why it was working on my PC. It probably shouldn't have been. I guess I was lucky that it failed so quickly on my clients computer or this could have bitten me down the road. > > It still could be a timing issue, > > Or another thousands of issues... > > > Also, the only advantage that I can see to having MainForm being the > > owner of the TClientSocket is that if something unexpected occurs and > > the TClientSocket doesn't get deleted somehow, the MainForm will free up > > the memory when the form gets destroyed. > > Not a big advantage. Almost a disadvantage under certain points of view. > I see that, now. > > This advantage is greatly decreased by the fact that the form is never > > destroyed until the program exits, in which case Windows is going to > > free up the memory anyway. > > Anyway, your thread should be strong enough to handle any possible problem > and free the TClientSocket pointer by itself. > > Did you find anything more in the meantime? > Not really. This definitely seems to have fixed my problem. It wouldn't run more than 30 minutes before. Now, it has run for days with no problems. > HTH, > > Stefano. > Thanks Stefano.
Re: Using TClientSocket in multi-threaded app
Author: Mark Atkin
Date: Wed, 26 Apr 2006 17:35
Date: Wed, 26 Apr 2006 17:35
99 lines
4749 bytes
4749 bytes
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message news:<444fab11$1@newsgroups.borland.com>... > > "Mark Atkin" <matkin@windrock.com> wrote in message > news:4447ee51$1@newsgroups.borland.com... > > > The next time the thread checks it's status, the thread calls new > > TClientSocket to allocate a new socket connection to use for > > the communication, retrieves the data, then deletes it's instance > > of TClientSocket. > > A better approach would be to create the TClientSocket instance only once > when the thread is created and then free the TClientSocket when the thread > is being freed. You don't need to create a new TClientSocket instance > over > and over during the thread's lifetime. Just Connect/Disconnect it when > needed. > I have thought about doing this. I still might. > > When I tried it on a client's computer, I began getting AVs when > > the thread was calling new TClientSocket. > > That is because of the way you are managing the TClientSocket. Keep > reading... > > > I was creating my instances of TClientSocket as follows: > > > > TClientSocket *sock = new TClientSocket(MainForm); > > That is not thread-safe. You are telling the TClientSocket to be owned by > a > TForm that resides in another thread. All of the ownership management > that > the VCL does internally only works when used in a single thread. In this > case, you should be using NULL instead to assign no owner to the > TClientSocket at all. The thread manages the TClientSocket's lifetime, so > there is no need to assign any owner anyway. > I don't know much about the internals of the VCL, but that was the only conclusion I could come up with. I'm glad to know you came up with the same conclusion. > > My theory as to why I would get AVs is that maybe all three threads > > are calling new TClientSocket(MainForm) almost simultaneously and > > basically, some method and/or property from my MainForm is being > > accessed by all three threads to add the TClientSocket component to > > the ComponentList array and increment the ComponentCount for the > > MainForm. > > That is very likely, yes. Which is exactly why specifying an Owner is not > thread-safe at all. > Unfortunately for me, this is the first experience I've had with writing multi-threaded applications. It's definitely been a learning experience. > > I changed the socket instantiation to new TClientSocket(NULL) and > > the problem has gone away. > > There you go then. > > > The biggest hole in my theory that I can see is that it doesn't really > > explain why it would work on my PC and not my clients. > > A fluke, nothing more. It is likely just a timing issue, which are very > difficult to debug. Maybe your computer is slower then the client's > computer and thus the problem doesn't show up as much on your machine > since > the main thread properties/members are not access quite as simultaneously. > Everything always works fine on the development system, right? :P > > Also, the only advantage that I can see to having MainForm being > > the owner of the TClientSocket is that if something unexpected occurs > > and the TClientSocket doesn't get deleted somehow, the MainForm > > will free up the memory when the form gets destroyed. > > That is a very bad design when threads are involved. You should not be > assigning ownership across threads. Each thread should own its own > objects. > If something goes bad and your main thread does not terminate the threads, > the threads will still be running when the main thread frees the objects > that the threads are using. > Again, I'm learning more all the time about using threads. > > Gambit > > Thanks Gambit.
Re: Using TClientSocket in multi-threaded app
Author: Remy Lebeau (TeamB)
Date: Wed, 26 Apr 2006 20:58
Date: Wed, 26 Apr 2006 20:58
15 lines
1575 bytes
1575 bytes
"Mark Atkin" <matkin@windrock.com> wrote in message news:444faf4f$1@newsgroups.borland.com... > I don't know much about the internals of the VCL, but that was > the only conclusion I could come up with. I'm glad to know > you came up with the same conclusion. I didn't "come up" with that conclusion. The behavior I described is a known fact. Besides, I have the VCL source code, so it is just a matter of looking up what the VCL actually does. Most of the VCL internals are NOT thread-safe, so you have to be VERY careful when using the VCL with threads. Gambit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads