Sign in to follow this  
Subotron

[.net] Aargghh, threading!

Recommended Posts

Hi, I'm working with Visual C# .NET (2.0), and I could not be more in love with a language. However, while I always ignored multithreading, I pretty much can't get away with that anymore, or so it seems. Multithreading seems great, but it also gives me massive headaches. So in advance, if you have any good resources on c# multithreading (I know how to start and stop a thread, but most articles stop at the point where my questions begin), please let me know. My actual problem is this: I run an engine (basically a class), which should operate side to side with one or multiple forms (and output data to those forms). For now I only had to use one form, and this worked fine with just a single thread (I ran the engine's main loop when there were no messages waiting to be handled). I had to do some invokes, because the engine uses asynchronous sockets for networking, and sometimes I apparently ended up in another thread (I understand why this is). However, then I tried to add a second form. This is where the trouble started. I tried in a lot of different ways to get 2 forms shown, and both would actually have a message loop that kept them from 'freezing'. But in each way I tried, I encounter one or more problems, related with cross-thread calls, not being able to create the 2nd form on the main thread, forms 'freezing', closing the 1st form results in ending the app (unwanted), etc. What I'm looking for is more insight in how I should handle these kinds of situations. My most important questions at this moment: 1. How can I control/find out in which thread I'm currently operating? 1b. If I can't control the thread, can I invoke a call on another thread even if I don't have a window handle for that thread? 2. How can I prevent/set that closing a single form exits my application? (I know it has something to do with application.Run versus form.ShowDialog versus form.Show, but I can't find out the details on when to use which, and what the resulting effects are.) 3. Is it at all a good idea to run the engine on a seperate thread from the forms? 4. Do I explicitly need to create a message loop for each form? Up till now Application.Run( someForm ) did the job for me, I'd like to keep it that way if possible, even when running multiple forms in parallel or sequential. 5. Currently it bothers me that my asynchronous sockets create threads that I can't really keep track of, is there an alternative? (I figured creating my own threads and using synchronous sockets is an option, but maybe you guys have a better suggestion?) 6. Are there any guidelines on when (not) to use seperate threads, or anything else I should know about? Any help on this matter is greatly appreciated. Using google I found some stuff, including a useful BackGroundWorker, but I am still confused as hell...

Share this post


Link to post
Share on other sites
1. System.Threading.Thread.CurrentThread. You can name your threads, even, to make it easier on yourself. As for moving one thread to another thread, not sure on that one, but if you find yourself having to do that I can only assume that the solution would be to ensure it starts in the correct thread.
2. The application terminates when all non-background threads are closed. Application.Run() blocks on the thread it is called so when the form used with Application.Run() closes, the method stops blocking and you finally run into the end of the Main() method.
3. Possibly... I would more state it as "run the forms on a separate thread than the engine". Your form should be doing nothing more than displaying updates from the engine so it should be able to just detach completely from one another. But I guess it depends on what they're doing, too.
4. Seeing as how Application.Run() blocks, you can only use it once per thread. I would probably just use Application.Run() for the primary form and AddOwnedForm for child forms.
5. I am guessing you are, when receiving a message for example, forwarding it straight to the message handler, correct? What you can do is queue the received messages then, in your engine's update loop, you can call a Heartbeat() method which will grab the information from this queue and process it. This way all messages will still be handled at a specific time on your update thread. The only threading issues you will have to deal with then, as long as you design it properly, is to block the queue from changing while you are reading from it.
6. When they're not needed? ;)

You can try checking out this for more information:
http://www.albahari.com/threading/index.html

Share this post


Link to post
Share on other sites
Thanks! That helps a lot!

1. Yeah I found out about this property. It's nice for debugging, but I can't seem to use it to 'call'/'activate' another thread. Indeed, I will have to ensure I start things in the correct thread, which is exactly what I want to achieve with being able to 'call' a certain thread.
2. So I could either run multiple threads, each with an Application.Run (or Form.ShowDialog()) call, or go for your solution proposed at 4.
3. Indeed, forums are used only for user in/output (e.g. in a map editor). Indeed, I should think of it as running the forms on a second thread, not vice versa.
4. I don't know AddOwnedForm, currently I use Form.Show (which isn't exactly what I want) so I'll look into it.
5. Very good point. I already had such a queue built up, but never used it like you suggest. It should work perfectly.
6. Doh :) it's a bad question of mine, actually it's more like an 'invite' to give me a lesson on not overusing threads and proposing awesome alternative solutions :)

Edit: Oh, just saw the link. Actually I found that e-book 30 minutes ago myself, but in PDF. This is better :)

Share this post


Link to post
Share on other sites
Threads aren't a magical solution to improve the framerate, imho. They are not free, they use resources; and while all new boxes have two or more cores, I still find advisable to not abuse of threading since context switching is always there waiting to bite back. Also, a bunch of threads and you'll eventually run out of cores.

Locking primitives have their associated cost too. If you have a producer/consumer queue, and you keep on adding items while the working thread elaborates the queue, you're better off bringing the work into the main thread, since you'd be locking / unlocking too often.

Long story short, threads are very useful but they have to be used carefully imho.



Share this post


Link to post
Share on other sites
Thanks for the warning. Currently I use 2 threads (main/forms and engine), and whatever the asynchronous sockets create on the bg. I only need a few locks, but yeah already my frametime is noticeably higher. I'll definetly use threads/locking as little as possible, but it did provide a great solution for me in this context :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this