I have a time consuming process which runs with an NSOperation.
I now need user's choice to choose between different subprocesses.
I need to stop the process until the user respond to the question.
How can I do this from an NSOperation?
Thanks
It should just be a matter of creating an NSAlert and calling runModal on it, making sure you're on the main thread. Have you tried that?
Perhaps in the method where you are creating the NSAlert, you can have assert([NSThread isMainThread]) at the top of the method and I think that this will assure that this method get executed on the main thread. I hope this helps!
Related
I need to implement a form with buttons and log widget, and when button is pressed, some long job should start in the other thread.
Details of the process should be echoed to the log.
Two jobs should not be started simultaneously.
The way I'm thinking about: create subclass of QThread with its own event loop (of course call moveToThread(this) in the QThread's constructor), and connect signal of QButton to the slot doLongJob() of this thread.
Does it sound good, or is it generally wrong? Other way: say, create new thread every time user pressed button. Seems to be worse.
Is there some best practices to do this pretty common thing? Please give me a suggestion.
Bard already answered in the comment, I asked him twice to write the same as an answer, but it seems he really doesn't want to.
So, I'm tired of waiting more than 7 months, and therefore have to do that myself, in order to get rid of this unanswered question.
The answer is:
You generally do not want to subclass QThread, but other than that, hooking up things with signals and slots is just fine.
In my application I run wglGetCurrentDC() and wglGetCurrentContext() from onThread function
(this function should be called as declared here - EVT_THREAD(wxID_ANY,MyCanvas::onThread))
and I get NULL in both cases. When I run it not from onThread it is ok…
What is work around in order to solve the problem – (I have to run them when getting event from the thread!)
As Alex suggested I changed to wxPostEvent to redirect the event to main thread, which catches the event in its onThread function.In this onThread function I have wglGetCurrentDC() and wglGetCurrentContext() calls ...They still return null.Please explain me what I am doing wrong. And how to solve he problem.
Maybe I'm misunderstanding, but should you not be using wxGLCanvas and wxGLContext rather than the windows-specific code? At the very least it's probably more compatible with other wxWidget code.
Anyway, from the wglGetCurrentDC documentation, the function returns NULL if a DC for the current window doesn't exist. This suggests that either the context was destroyed somehow or you're not calling it from the window you think you're calling it from (perhaps because of your threading?). I would reiterate what Alex said; don't call UI code from any thread besides the main one.
If you could post some code showing how you're returning from the thread it might help identify the problem. It seems likely that you're doing UI stuff from the thread and just not realizing it. (Hard to tell without seeing any code, though.)
Don't touch any UI-related stuff from a worker thread. This is general requirement for all UI frameworks. Use wxPostEvent to redirect a work to the main application thread.
I wrote a function that does alot of mathematical operations and it takes about 10 minutes to finish its work. I tried to call this function via a button on a form (Windows forms application). But the problem now is during the 10 minutes, the main form stops to respond till the function is finishing its work.
How can i solve this... any idea!
You might assign a new thread for the calculations so that the form would not have to wait for the calculation to finish to continue execution (i.e. listening to and responding to events etc.)
The problem is that, while your 10 minute function is working, the rest of the program is not executed. In particular, it cannot execute the rendering. (i.e. making your form respond).
The solution is to use threads.
As already mentioned you should assign long running tasks to a worker thread or a threadpool thread.
Keep in mind that there are limited numbers of threadpool thread. ALso Windows forms is not thread safe so you should not be directly updating the form from the created thread. You can make use of InvokeRequired.
In this case better to use BackgroundWorker class. Details in following link.
http://stuff.seans.com/2009/05/21/net-basics-do-work-in-background-thread-to-keep-gui-responsive/
Actually i am using this code and works ok, but i 'am wondering if is the correct way.
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
The VCL TThread class has its own WaitFor() method that pumps the main message queue internally when called within the main thread context:
MyThread.WaitFor;
ShowMessage('i am done');
Calling Application.ProcessMessages is generally considered a code smell. Let your main thread idle if it's got nothing to do.
If you ran a company and needed one of your workers to run to the store and grab some much-needed supplies, would you then pace by the door until he got back, or would you prefer to sit in your office and rest and wait for him, and find out that the supplies are here because you hear him walk through the door? Either way, he'll take the same amount of time, but the first way's gonna wear your legs out.
Similarly, instead of having your UI watch the thread, have the thread report back to the UI. One way to do this is to have the thread use PostMessage to send a custom message to the form that launched it once it's finished, and put a message handler on the form to respond to it.
It looks correct (if correct means it do the work). What I would change is to wait for a bit more time (50ms looks good to maintain the application responsive) while not eating CPU.
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
Sure there are other ways to do it... <joke>but I usually apply one of the main engineering principles:
if it works, don't touch it!</joke>
I agree with Mason Wheeler's remark, the main thread is best left to do its job, but I would suggest using the OnTerminate event on the thread. It is more 'Delphi natural' and the internal logic does the PostMessage bit for you. Since TThread is not a component, you can't view it in the object inspector and have to write and attach an event handler yourself. It gets called (in the main thread!) after the thread has completed/terminated.
While it looks okay, like jachguate I would use a bigger time-out value than 0 too. If you use WaitForSingleObject(MyThread.Handle, 100) then the main thread will wait a bit longer, thus eating up less CPU cycles.
A better solution would be the use of messages, though. Your application starts the thread and then puts all controls in disabled mode. The thread then executes and when it's finished, use SendMessage or PostMessage to the main window to notify it that the thread is done again. Then your application will just enable every control (and whatever else) again. This has as advantage that you keep the "natural" messageloop for the application alive, instead of running your own messageloop with this solution.Unfortunately, the message-method has one drawback: if the thread crashes then no message will be sent back, so a backup plan would be practical. For example, by adding a timer control to your mainform which checks every second if the thread is still alive. If not, it too would just activate the form again, disabling itself again.
I have a worker thread in a class that is owned by a ChildView. (I intend to move this to the Doc eventually.) When the worker thread completes a task I want all the views to be updated. How can I make a call to tell the Doc to issue an UpdateAllViews()? Or is there a better approach?
Thank you.
Added by OP: I am looking for a simple solution. The App is running on a single user, single CPU computer and does not need network (or Internet) access. There is nothing to cause a deadlock.
I think I would like to have the worker thread post (or send) a message to cause the views to update.
Everything I read about threading seems way more complicated than what I need - and, yes, I understand that all those precautions are necessary for applications that are running in multiprocessor, multiuser, client-server systems, etc. But none of those apply in my situation.
I am just stuck at getting the right combination of getting the window handle, posting the message and responding to the message in the right functions and classes to compile and function at all.
UpdateAllViews is not thread-safe, so you need to marshal the call to the main thread.
I suggest you to signal a manual-reset event to mark your thread's completion and check the event's status in a WM_TIMER handler.
suggested reading:
First Aid for the Thread-Impaired:
Using Multiple Threads with MFC
More First Aid for the Thread
Impaired: Cool Ways to Take Advantage
of Multithreading