Aborting XNA main thread? - c#

I'm currently shifting a game that I created from XNA's sequential approach (consecutive calls of Updates and Draws) into a multi-threaded approach.
I've already succeeded in moving game updates and draws to other tasks/threads. The only issue I'm having is figuring out how to abort the main XNA thread (the class that extends the Game class) because I literally have empty Update() and Draw() methods.
When I attempt to abort that thread via:
System.Threading.Thread.CurrentThread.Abort();
as the last line of the Initialize() method of the Game class, the entire application terminates. So, is there a way to terminate the main thread of XNA and still have the game window executing? The reason I'm trying to terminate this thread is that I don't want it to impact the performance of the game by executing empty Update/Draw.

Well - you really don't want to abort the main thread. That thread owns the window XNA is using for display, and you can only do input on the main thread (that is: Mouse.GetState, Keyboard.GetState, etc).
Calling Abort on it is equivalent to raising a ThreadAbortException, which will bubble up and (in the default Program.cs template) clean up your game instance (see the using statement).
Consider simply using that main thread as the thread responsible handling Update or Draw.
But if you've really got your heart set on doing this, you can stop XNA from pumping updates with this code:
Application.Idle = null;
(Requires referencing and using System.Windows.Forms.)
You can perhaps use Game.RunOneFrame or Tick if you wanted to continue using functionality in Game. No idea about the wonderful ways in which XNA might explode if you tried to call these methods off-thread.
If you don't use them, you'll need to provide your own timing code, you'll need to call FrameworkDispatcher.Update regularly (required for audio).
Either way you'll have to figure out a way to perform input on the main thread. The Win32 message loop will still be running on that thread (or, rather, blocking), so you'll need to hook into that to do your input.

Related

SetWindowPos even when the main thread is blocked?

I'm trying to make my program move itself via a call to SetWindowPos every 10 milliseconds, to follow the cursor. Problem is, when my program's main thread is blocked by a Thread.Sleep(), the window stops moving.
I put the call to SetWindowPos into a secondary System.Thread, but it's still blocked. It appears that SetWindowPos is always handled by the thread that owns the window. So if my main thread is busy, the window can't be moved, even if the request is sent from a different thread.
Is there an alternative way to move a window, even when the thread that owns the window is busy? Thanks!
I don't believe so. All UI operations must be performed on the primary application thread which is known as the UI thread in a GUI app. Whether it is a button click event; mouse move; scroll; paint etc including move window, these operations are queued in the applications message queue (sort of like a FIFO buffer that Windows maintains for all apps) which must be processed by the UI thread.
If say a button click event takes a long time becuase the programmer decided to perform a lengthy database operation in the same thread as the callback, then the UI will freeze until the callback is complete which happens to be the database code.
Similarly if somewhere in your UI thread code you have a Thread.Sleep(), then the UI will also freeze during the same period.
Alternatives
You might want to consider moving lengthy operations to another thread or go the easy contempory and recommended way and use async/await. Doing so allows you to perform the lengthy operation without blocking the UI.
Timers
Also, consider using a Timer instead of Thread.Sleep() or equivalent as an alternative to moving the window 100 times a second. Be sure to use the right timer for GUI apps as .NET defines at least four (4) I believe and not all are suitable by default (if at all) for GUI apps.

Multithreading with Game Engines (Unity3D)?

I am using Unity3D and Mono to make a multiplayer online game. The language is C# script. I know that Unity is not thread safe. C# in Mono allows you to create a new thread using System.Threading. But Unity would forbid the new thread from modifying any of the GameObjects.
In my code I started a new thread to wait for a callback from some of my native C code (incorporated into Unity as Plugins). In this way, when the callback gets called it will be on the new thread, not Unity's main thread which has the authority to manipulate GameObjects. However, I want the GameObjects to be modified. What should I do? Should I use the main thread to poll the new thread? Or is there any better solution?
There is more than one way to signal a main thread that data is available on a 2nd thread. Generally speaking, the first way might be to have the first thread "block" (wait) until the 2nd thread "signals"; however, without going into detail here this is not the approach you want to take, because blocking the main thread while you perform lengthy computations on your 2nd thread will make your game unresponsive at worst or jittery at best.
So this leaves the other approach which you brought up: polling. However often you feel necessary (once per frame, once every 60 frames), your main thread code (e.g. in a MonoBehaviour) will want to check on the status of the task in the 2nd thread. This could be via calling a method or checking a boolean value on an object "owned" by the 2nd thread. Via this approach, your task will indicate to the main thread polling whether things are "done" or "not done". Unity co-routines might be a useful mechanism for implementing your polling logic from the main thread.
However, you are not necessarily done yet. If your 2nd thread is going to repeatedly generate new data into the same variable or buffer, you have to also make sure your main thread will not read from a buffer that is being written by your 2nd thread to at the same time. For small amounts of data, you can use a double-buffering approach (two buffers/variables, one for reading, one for writing, which are swapped via pointer/reference exchange) when new data is ready; or you can use C# locks (but this can block your main thread with the side-effects described earlier).
Once your main thread has the data it needs, you can then of course proceed to modify your game objects from the main thread.
Note that your question is not all that specific to Unity. Most UI frameworks have this limitation (with good reason), and communication between threads is solved in similar ways in each instance.

interface freezes in c# multi-threaded app

I have a c# .NET multi-threaded application that is freezing the interface. What is unusual about this is that the interface does not freeze unless I let the system sit idle long enough for the screen saver to start (which requires me to reenter my password to re-gain access to the system). When the interface becomes visible again (after I have successfully entered my password) all the windows are white. I can see the window titles, move the windows around, minimize them and such, but the screens are not repainting. When I break all and enter the debugger, the call stack has Application.Run(), external code, and then "in a sleep, wait, or join". I put break points in all four of the threads I open and they are still running, it is just the main app's UI thread that is blocked. When I look at my thread list, what was my main thread and my four worker threads now consists of my main thread and 11 worker threads. I didn't open this many threads so it must be the serialport class.
Now let me describe my program.
My main app allows users to collect and monitor data from serial ports. I have implemented this in the following way. When a connection is desired, a button is pressed on the main app which calls a function in a DLL which opens a status window and then launches a thread which monitors the serial port. When that function returns, the main app launches a thread to monitor a queue created in the DLL when it is initialized. When data is received from the serial port, the data is parsed and then the status window is updated (via a delegate) and the data is pushed onto the queue. When the main apps worker thread sees data in the queue it retrieves it and posts it in a list box on the main app, using a delegate. In all cases I use BeginInvoke to call these delegates.
My DLL contains two libraries for the two different types of equipment it can communicate with.
This problem occurs when I have a connection to two devices; hence the four worker threads two for each device. The DLL itself is setup as a comm object so I can access it easily from a C++/MFC app and a c# app, both of which utilize it.
I found that if I add code to the thread inside the DLL so it calls Application.DoEvents() every 30 seconds, the interface will be frozen for about 30 seconds and then resume activity like normal. I figure something is blocking the main thread and forcing DoEvents() to fire seems to break the lock, but I have no idea what might be causing this lock. This is not a solution, just something of interest.
I would appreciate any suggestions you might have. Thanks.
I found that if I add code to the thread inside the DLL so it calls Application.DoEvents() every 30 seconds, the interface will be frozen for about 30 seconds and then resume activity like normal. I figure something is blocking the main thread and forcing DoEvents() to fire seems to break the lock, but I have no idea what might be causing this lock. This is not a solution, just something of interest.
I would recommend running your program under the new Visual Studio 2010 Concurrency Profiler. This will show you, at runtime, which threads are blocked, and which objects they are waiting on. Thread contention is explicitly marked and highlighted for you.
You can use this to easily determine what code is causing the deadlock on your UI thread.
Try changing your Thread Start code to Thread.Start() instead of BeginInvoke(). BeginInvoke does not keep threads tryky seperate from your UI, as it and it may be interacting strangely with DoEvents. You can read up on BeginInvoke and how it works here: http://www.codeproject.com/KB/cs/begininvoke.aspx
Also, DoEvents is NEVER necessary in an application, and can cause a lot of unexpected behavior. Use threadding with UI calls wrapped in a Control.Invoke(...) statement. If you're using .NET 3.5+, you can make this easy with delegates that look like this: Invoke((Action)delegate() {*code goes here*});

Reading input from secondary thread

I have an XNA application, and I need to redirect the input queue into a custom thread, instead of having it available only in the main thread. Is there an alternative to AttachThreadInput?
I did some searching on this, and I don't think you're going to find a great way to solve this. This post indicates that it may be possible if you "make a new input class, register those events in my games main thread, then start the thread to begin polling."
The general consensus from these two threads (including the one you started on the XNA forums) indicates to me that trying to send keyboard input to a different thread probably isn't the best idea, and that, if possible, the main thread should just handle the keyboard input and the other thread can read the input from the main thread's shared storage. An alternative would be the main thread telling the secondary thread to do certain functions based on what input it received.
Keyboard access from other thread
Keyboard Input on Another Thread
I'm not quite sure what you're asking, but I'll try to answer.
If you're trying to create a multi-player game and want input for each player to be handled by a thread you have to do the following:
Create the XNA objects related to Keyboard/Mouse/Gamepads in the main
execution thread of your
application
Pass the objects by reference to your custom input handling thread.
Threads share memory with the processes that spawn them, so any changes made to the object from inside your custom thread will be automatically accessible outside the thread by using your referenced object.
Hope this helps.

Multithreading on Windows Forms

I want to paralelize a 3D voxel editor built on top of Windows Forms, it uses a raycaster to render so dividing the screen and getting each thread on a pool to render a part of it should be trivial.
The problem arises in that Windows Forms' thread must run as STA - I can get other threads to start and do the work but blocking the main thread while waiting for them to finish causes strange random deadlocks as expected.
Keeping the main thread unblocked would also be a problem - if, for example, the user uses a floodfill tool the input would be processed during the rendering process which would cause "in-between" images (an object partially colored, for example). Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
I want to know if there is any workaround to get the amin thread to appear blocked to the user in a way that it will not be actually blocked but will delay the processing of input till the next frame.
If it isn't possible, is there a better design for dealing with this?
EDIT: Reading the anwsers I think I wasn't clear that the raycaster runs in real time, so showing progress dialogs won't work at all. Unfortunately the FPS is low enough (5-40 depending on various factors) for the input between frames to produce unwanted results.
I have already tried to implement it blocking the UI thread and using some threads of a ThreadPool to process and it works fine except for this problem with STA.
This is a common problem. With windows forms you can have only one UI thread. Don't run your algorithm on the UI thread because then the UI will appear frozen.
I recommend running your algorithm and waiting for it to finish before updating the UI. A class called BackgroundWorker comes pre-built to do just this very thing.
Edit:
Another fact about the UI thread is that it handles all of the mouse and keyboard events, along with system messages that are sent to the window. (Winforms is really just Win32 surrounded by a nice API.) You cannot have a stable application if the UI thread is saturated.
On the other hand, if you start several other threads and try to draw directly on the screen with them, you may have two problems:
You're not supposed to draw on the UI with any thread but the UI thread. Windows controls are not thread safe.
If you have a lot of threads, context switching between them may kill your performance.
Note that you (and I) shouldn't claim a performance problem until it has been measured. You could try drawing a frame in memory and swapping it in at an appropriate time. Its called double-buffering and is very common in Win32 drawing code to avoid screen flicker.
I honestly don't know if this is feasible with your target frame rate, or if you should consider a more graphics-centered library like OpenGL.
Am I missing something or can you just set your render control (and any other controls that generate input events) to disabled while you're rendering a frame? That will prevent unwanted inputs.
If you still want to accept events while you're rendering but don't want to apply them until the next frame, you should leave your controls enabled and post the detail of the event to an input queue. That queue should then be processed at the start of every frame.
This has the affect that the user can still click buttons and interact with the UI (the GUI thread does not block) and those events are not visible to the renderer until the start of the next frame. At 5 FPS, the user should see their events are processed within 400ms worst case (2 frames), which isn't quite fast enough, but better than threading deadlocks.
Perhaps something like this:
Public InputQueue<InputEvent> = new Queue<InputEvent>();
// An input event handler.
private void btnDoSomething_Click(object sender, EventArgs e)
{
lock(InputQueue)
{
InputQueue.Enqueue(new DoSomethingInputEvent());
}
}
// Your render method (executing in a background thread).
private void RenderNextFrame()
{
Queue<InputEvent> inputEvents = new Queue<InputEvent>();
lock(InputQueue)
{
inputEvents.Enqueue(InputQueue.Dequeue());
}
// Process your input events from the local inputEvents queue.
....
// Now do your render based on those events.
....
}
Oh, and do your rendering on a background thread. Your UI thread is precious, it should only do the most trivial work. Matt Brundell's suggestion of BackgroundWorker has lots of merit. If it doesn't do what you want, the ThreadPool is also useful (and simpler). More powerful (and complex) alternatives are the CCR or the Task Parallel Library.
Show a modal "Please Wait" dialog using ShowDialog, then close it once your rendering is finished.
This will prevent the user from interacting with the form while still allowing you to Invoke to the UI thread (which is presumably your problem).
If you don't want all the features offered by the BackgroundWorker you can simply use the ThreadPool.QueueUserWorkItem to add something to the thread pool and use a background thread. It would be easy to show some kind of progress while the background thread was performing it's operations as you can provide a delegate callback to notify you whenever a particular background thread is done. Take a look at ThreadPool.QueueUserWorkItem Method (WaitCallback, Object) to see what I'm referring you to. If you need something more complex you could always use the APM async method to perform your operations as well.
Either way I hope this helps.
EDIT:
Notify user somehow that changes are being made to the UI.
On a(many) background threads using the ThreadPool perform the ops you need to perform to the UI.
For each operation keep a reference to the state for the operation so that you know when it completed in the WaitCallback. Maybe put them in some type of hash / collection to keep ref to them.
Whenever an operation completes remove it from the collection that contains a ref to the ops that were performed.
Once all operations have completed (hash / collection) has no more references in it render the UI with the changes applied. Or possibly incrementally update the UI
I'm thinking that if you are making so many updates to the UI while you are performing your operations that is what is causing your problems. That's also why I recommended the use of SuspendLayout, PerformLayout as you may have been performing so many updates to the UI the main thread was getting overwhelmed.
I am no expert on threading though, just trying to think it through myself. Hope this helps.
Copying the entire image before every frame isn't doable either because the volumes are big enough to offset any performance gain if it has to be copied every frame.
Then don't copy the off-screen buffer on every frame.

Categories