I have a window which runs from a thread, let's call it MainThread, and a background thread which performs other non-graphical tasks.
Sometimes the background thread will call the MessageBox.Show(...) method (which is modal and stops the background thread). Before this call, I would like to suspend the MainThread and resume it after so that my MainWindow's controls are disabled while the messageBox is shown.
So my questions are:
How do I access the mainThread from the backgroundThread?
How do I suspend/resume it (Considering Thread.suspend is depricated)?
Instead of suspending the main thread, you could use Control.Invoke (Windows Forms) or Dispatcher.Invoke (WPF) to actually show the message box on the main thread, but call it from your background thread.
In addition to providing the behavior you wish, this would also have that advantage of allowing you to parent your message box to the proper Window, which would give the proper modal message box behavior.
Related
I have a notification which can be posted on a background thread. This notification eventually leads to calling setTitle:forSegmentAtIndex:, which is UISegmentedControl, part of the UIKit.
Should it be assumed that I need to wrap this setTitle:forSegmentAtIndex: call with a async call to main thread, or will some lower lying Cocoa code automatically dispatch anything like setTitle:forSegmentAtIndex: to the main thread?
Always dispatch code that modifies a UI control to the main queue. Always.
I am not clear about what does waitUntilDone do, but I found this thread:
What is the significance of WaitUntilDOne in performSelectorOnMainThread?
which makes me a bit clear, however, if I perform some selector which makes NSURLConnection(which is asyncrhonous) and waitUntilDone set to YES, what will happen then? It will wait for the method to execute, but the method actually does some asynchronous operation(ie NSURLConnection), then what is the impact?
Thanks!
NSURLConnection is asynchronous. Your code runs on the main thread, and it makes delegate calls to you as the download progresses. You don't need to, and should not, run an NSURLConnection from a background thread.
If you DO have code that needs to run on a background thread, you can use the preformSelectorOnMainThread method to send messages from your worker thread to the main thread. One common reason to do this is that you can't update the UI from a background thread. You'd invoke a method to update the UI on the main thread.
The flag waitUntilDone controls what happens after the performSelectorOnMainThread call. If waitUntilDone is false, your background thread continues on with the next line without waiting for the code on the main thread to finish.
If waitUntilDone is true, your background thread will block until the main thread finishes performing the selector that you sent it.
I have issue:
One thread raises event that is listened from main thread.
Main thread in eventHandler raises
message dialog like this:
MessageDialog md = new MessageDialog (parent_window, flags, msgtype, btntype, msg);
md.Run ();
md.Destroy();
However application crashes on md.Run(); (if i raise messageDialog using gtk.application.invoke() there is no crash but there is also no modality in dialog.)
GTK objects can only be accessed safely from the main thread. If you subscribe to an event from the main thread, that does not mean that the event will be raised from the main thread. Events are raised on the thread that raises them.
What you need to do is to use Application.Invoke to safely queue a delegate on the main thread's mainloop, and access the GUI objects from that delegate. You can do this in the event handler, or you could even use a delegate to dispatch the event onto the main thread, so that event handlers would not have to do so - it's just a question of how you want to define your internal API.
Note that although Application.Invoke runs the delegate asynchronously, this does not affect the modality of the dialog. The thing that affects the modality of the dialog is whether you include the DialogFlags.Modal flag in the flags parameters.
I have a window that displays some data in an NSTableView. This data is loaded in the background. The data-loading-thread is started in the windowDidLoad: method. If the window is closed before loading has finished, the background thread should be cancelled. I do this by signalling the thread in the windowWillClose: delegate method and waiting for the background thread to finish.
Now this all works perfectly. But I have one problem: How can I update the data in the table view? I have tried calling reloadData via performSelectorOnMainThread: but this leads to a race condition: The reloadData call is sometimes queued on the main thread after the window close command, and will execute after the window has closed, and everything goes up in flames.
What's the best way to control and communicate with a background thread?
Well, you know, this is exactly what makes the use of threading complex: you always face synchronization issues.
What I suggest is, instead of calling [tableView reloadData] from your thread, simply signal your controller (by calling a method controllerShouldReloadTable) and let your controller do the check if windowWillClose has been called or not. There might be a chance that your controller has been also released by the time controllerShouldReloadTable, and to fix this you will definitely need to retain the controller from the secondary thread.
On a side note, I would cancel the thread in viewDidUnload (for symmetry).
Most important: I would use asynchronous calls and a delegate class so that the whole multithreading issue is solved at its root.
EDIT: Sending asynchronously a request will not block the sending thread waiting for the response. Instead, asynchronous send (for NSURLConnection is called start) immediately returns (so, no blocking) and when the response is received, a delegate method will be called (i.e., connectionDidFinishLoading:) so that you can updated the model and the UI. Take a look at NSURLConnection docs, but as usual, I strongly suggest using [ASIHTTPRequest][2], which has many advantages.
When I start a 2nd background thread and pause the main thread, will my First Responder still be in action? For example I have an overwriting method called -flagsChanged and was wondering if it would still be active if the main thread is offline.
Thanks,
Kevin
Don’t pause the main thread since the main thread is responsible for handling events and your application UI will become irresponsive. If the main thread is paused, it won’t handle events, hence it won’t dispatch key events to the first responder.
If you think you need to pause the main thread, you probably need to redesign your program so that the behaviour that requires sleeping (if it does require sleeping) is offset to a secondary thread. If you need to update the user interface from a secondary thread, you should use -performSelectorOnMainThread:withObject:waitUntilDone:.