I have a background thread that polls UI thread every 200ms. If there is a hang for 2 seconds, I would like to get the call stack from UI thread at that point. When I call [NSThread callStackSymbols], it is executed on background thread since I check If the hang is more than 2 secs in background thread.
is there an easy way to get call stack on main thread from bg thread?
Here is how to do it "manually".
Well, if I understand you right one of the threads is doing some heavy lifting which takes too long time. For these cases I just hit the pause button in xcode to pause the debugger. Then it is easy to inspect the callstack and see which method is blocking from continuing.
Related
I have a TListView in the main Form (Thread) and many other threads that add/delete item from the list using Synchronize method. But the main thread has also a method that modify the list items and I want that method not to be interrupted by other threads that wants to execute code in the main thread. Is this possible ?
Do you have evidence that what you are worried about is happening? You shouldn't, because it can't happen. That is what Synchronize is for. Methods executing in the main thread must complete before the main thread can service the message queue to process work items dispatched via Synchronize from worker threads so you have nothing to worry about.
When a worker thread uses Synchronize it essentially just posts a message to the main thread telling it that it has work for it to do. If the main thread is busy executing another method then the worker thread will simply block until the main thread is finished, subsequently processes the message queue, picks up the work item, executes it, and then posts back to the worker thread that the work is complete (leaving the worker thread free to then continue).
This, of course, assuming that the method in your main thread is not calling Application.ProcessMessages() or CheckSynchronize() (or you are using a tricky component that does this, or something similar, without you knowing it -> see : Delphi 7, Windows 7, event handler, re-entrent code)
I have the following problem:
I have 6 equal threads and a free main UI thread.. But the 6 threads are heavily invoking on the main thread to update its controls... The question is: How can I let the main thread stop one of the threads with a button and then continue the flow in the button, while the other threads are still able to invoke on the main thread? the other threads may not stop at any time.. I just want to stop one of the threads, and then continue the code in my flowchart.. while the other threads are not harmed of the thread stop..
I'm using VB.NET 2010 on a Core i7
Is there any analog for Delphi that specify that some thread is background thread? As for .NET I can say SomeThread.IsBackground = true; and this thread will become background.
Thanks in advance!
The .net documentation describes the IsBackground property like this:
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.
A Delphi process terminates when the main function in the .dpr file completes. This main function always runs in the context of the main process thread, that is the thread that is automatically created by the system when the process starts.
So, in Delphi there is no equivalent property. There is a single foreground thread, the main thread, and all other threads are background thread, using the .net terminology. A thread cannot, at runtime, change state from foreground to background, or vice versa.
To verify that the current thread is the main VCL thread, check TThread.CurrentThread.ThreadID = MainThreadID(*). The main VCL thread is supposed to stay the foreground thread, and is the only thread where the GUI should be updated, so the answer to your question is "no".
If you are using a recent version of Delphi you can however make use of TThread.CreateAnonymousThread and TThread.Synchronize in order to have anonymous methods executed in either a background thread or in the main VCL thread, respectively.
*) Please note that the CurrentThread class property was added only a few versions back. If you are using an old Delphi version, such as Borland Delphi 7, you can only perform this check from within the execute method of the thread (or from any method that is called by Execute etc).
In Delphi, every thread except the main thread is a background thread. That's why you can only update the GUI from the main thread.
What is the best was to do STA thread synchronization?
I have a dialog based MFC application with two STA threads: the main and the second. I created the COM object in the main UI thread.
I call the COM interface from the second thread. In the main thread, to make sure the second thread finishes before the main thread proceeds, I use a loop to wait for the thread. This loop calls MsgWaitForMultipleObjectsEx(timout=500) looply.
I immediately got deadlocked on the wait. Then I realized that the MFC message pump, AfxInternalPumpMessage(), only helps with blocking calls but doesn't help at all with deadlock situations.
Then I added Peek/Translate/DispatchMessage code into the wait loop and then all worked.
Now, it seems that without hand coding the Peek/Translate/DispatchMessage loop, you can't do STA threads synchronization at all? Any wait call will deadlock you. Then what's the best or standard way to synchronize STA threads?
Thanks!
Perhaps you are looking for CoWaitForMultipleHandles?
If the caller resides in a single-thread
apartment, CoWaitForMultipleHandles enters the COM modal loop, and the thread's
message loop will continue to dispatch
messages using the thread's message
filter. If no message filter is registered
for the thread, the default COM
message processing is used.
Not any wait, but any wait that stops running the message loop will indeed deadlock you. The solution is to interleave your wait loop and message loop processing - wait a little, then process all pending messages, repeat.
Given a System.Timers.Timer, is there a way from the main thread to tell if the worker thread running the elapsed event code is still running?
In other words, how can one make sure the code running in the worker thread is not currently running before stopping the timer or the main app/service thread the timer is running in?
Is this a matter of ditching Timer for threading timer using state, or is it just time to use threads directly?
Look up ManualResetEvent, as it is made to do specifically what you're asking for.
Your threads create a new reset event, and add it to an accessible queue that your main thread can use to see if any threads are still running.
// main thread owns this
private List<ManualResetEvent> _resetEvents;
...
// main thread does this to wait for executing threads to finish
WaitHandle.WaitAll(_resetEvents.ToArray(), 2000, false)
...
// worker threads do this to signal the thread is done
myResetEvent.Set();
I can give you more sample code if you want, but I basically just copied it from the couple articles I read when I had to do this a year ago or so.
Forgot to mention, you can't add this functionality to the default threads you'll get when your timer fires. So you should make your timer handler be very lean and do nothing more than prepare and start a new worker thread.
...
ThreadPool.QueueUserWorkItem(new WaitCallback(MyWorkerDelegate),
myCustomObjectThatContainsAResetEvent);
For the out of the box solution, there is no way. The main reason is the thread running the TimerCallback function is in all likelihood still alive even if the code running the callback has completed. The TimerCallback is executed by a Thread out of the ThreadPool. When the task is completed the thread does not die, but instead goes back into the queue for the next thread pool task.
In order to get this to work your going to have to use a manner of thread safe signalling to detect the operation has completed.
Timer Documentation