Xcode's "thread list" pane shows English-like names for several special threads: com.apple.main-thread, com.apple.libdispatch-manager, com.dispatchfractal.opencl, com.dispatchfractal.opengl, com.apple.root.low-priority,... But for user-created threads that field is just blank.
Is there any way to set that "thread name" field programmatically from my application? For example, if I've got a thread devoted to network I/O, I'd like it to show up as "com.example.network-io" in the debugger; if I spawn five worker threads I'd like to be able to name them "worker A", "worker B", etc. Does Xcode pull its thread-names from some API that I could hook into myself? Maybe something like CFAssignDebuggerNameToCurrentThread? :)
Probably not exactly what you want but NSThread has setName: method that allows you to set thread's name, you can attach meaningful name to the thread so you'll get the following in debugger:
[[NSThread mainThread] setName:#"That is main thread!"];
Remember also that some apis (like grand central dispatch) operate with thread pools so you are not guaranteed on what thread your operation will be performed
Edit:
com.apple.main-thread, com.apple.libdispatch-manager etc are labels of corresponding dispatch queues. You can set label value when queue is created with dispatch_queue_create function and later get it from the queue using dispatch_queue_get_label function.
It seems there's no API to change label value of the existing dispatch queue and I would not advise to change labels of the system queues anyway.
If you can get a reference to the thread whose name you want to change, you can change it in the debugger console. Two ways to do that for the current thread:
(lldb) po [[NSThread currentThread] setName:#"foo"]
(lldb) expression (void)[(NSThread*)[NSThread currentThread] setName:#"foo"];
I'd guess you could do the same from a breakpoint that has an associated expression. If you have a method that you know will run in the thread that you're interested in, you could set a breakpoint containing one of the above commands and have it automatically continue after running the command. That'd have the effect of automatically setting the name of the thread every time you run the code, which might be handy for debugging.
I use the following code in Swift 5 to rename the current thread:
pthread_setname_np("myThreadName")
pesudo code for -[NSThread setName:]
- (void) setName:(NSString*)thname {
if (self == [NSThread currentThread])
{
pthread_setname_np([thname UTF8String]);
}
else { ... }
...
}
So, the easist way to set name is calling pthread_setname_np.
Related
Does anyone know how to detect when the user changes the current input source in OSX?
I can call TISCopyCurrentKeyboardInputSource() to find out which input source ID is being used like this:
TISInputSourceRef isource = TISCopyCurrentKeyboardInputSource();
if ( isource == NULL )
{
cerr << "Couldn't get the current input source\n.";
return -1;
}
CFStringRef id = (CFStringRef)TISGetInputSourceProperty(
isource,
kTISPropertyInputSourceID);
CFRelease(isource);
If my input source is "German", then id ends up being "com.apple.keylayout.German", which is mostly what I want. Except:
The results of TISCopyCurrentKeyboardInputSource() doesn't change once my process starts? In particular, I can call TISCopyCurrentKeyboardInputSource() in a loop and switch my input source, but TISCopyCurrentKeyboardInputSource() keeps returning the input source that my process started with.
I'd really like to be notified when the input source changes. Is there any way of doing this? To get a notification or an event of some kind telling me that the input source has been changed?
You can observe the NSTextInputContextKeyboardSelectionDidChangeNotification notification posted by NSTextInputContext to the default Cocoa notification center. Alternatively, you can observe the kTISNotifySelectedKeyboardInputSourceChanged notification delivered via the Core Foundation distributed notification center.
However, any such change starts in a system process external to your app. The system then notifies the frameworks in each app process. The frameworks can only receive such notifications when it is allowed to run its event loop. Likewise, if you're observing the distributed notification yourself, that can only happen when the event loop (or at least the main thread's run loop) is allowed to run.
So, that explains why running a loop which repeatedly checks the result of TISCopyCurrentKeyboardInputSource() doesn't work. You're not allowing the frameworks to monitor the channel over which it would be informed of the change. If, rather than a loop, you were to use a repeating timer with a low enough frequency that other stuff has a chance to run, and you returned control to the app's event loop, you would see the result of TISCopyCurrentKeyboardInputSource() changing.
I have a simple code that does this:
private List<DicomImage> img = new List<DicomImage>();
Parallel.ForEach(ofdmulti.FileNames, filename =>
{
img.Add(new DicomImage(filename));
Progress_Bar_Loading_Images.PerformStep();
}
);
When I execute it, I get an error:
"Cross-thread operation not valid: Control 'Progress_Bar_Loading_Images' accessed from a
thread other than the thread it was created on."
How can I solve that without removing the progress bar? I really need it to show the progress
When you use Parallel.Foreach, each iteration (or a group of it) is perfomed on another thread (luckly on a different processor) concurrently. However, progressbar is working on main thread (or GUI thread) so you need to synchronize your threads after each call to progress bar.
An important thing to mention in here is synchronizing for each step is slow and pointless.So I suggest you to put a condition dependent on the modulus of an index to say "synchronize for each 10 steps".
I have a Main Thread that displays an interface, within another thread created from the main thread before the Main interface is shown, I create tow other windows sequentially:
I create the first window:
CWarningDlg warnDlg;
warnDlg.Create(NULL);
warnDlg.ShowWindow(SW_SHOW);
warnDlg.BringWindowToTop();
CMessageLoop _Loop ;
if(_MyAppModule.AddMessageLoop(&_Loop))
{
nRet = _Loop.Run();
_MyAppModule.RemoveMessageLoop();
}
warnDlg.DestroyWindow();
if (nRet == SOME_VALUE)
{
doSomethingElse();
}
Do something else has:
CActionDlg actDlg;
actDlg.Create(NULL);
actDlg.ShowWindow(SW_SHOW);
actDlg.BringWindowToTop();
CMessageLoop _Loop ;
if(_MyAppModule.AddMessageLoop(&_Loop))
{
CreateAnObject(); //this also launches an object Specific Worker Thread
nRet = _Loop.Run();
_MyAppModule.RemoveMessageLoop();
}
The function CreateAnObject calls some functions from a 'ComplexObject.DLL' that create an complex object which holds the THREAD ID of the thread that called the CREATION function, it gets it with ::GetCurrentThreadId(); , while creating this complex object the GetCurrentThreadId() returns the ID of the SECOND THREAD, which is GOOD.
Now, in my CActionDialog I receive notifications from this object usind ::SendMessage(), the SendMessage function is called from within a Worker thread that is specific to the Complex Object just created.
When I receive those notifications I need to access some of that complex object values, for that I call some other functions from 'ComplexObject.DLL' which verify using the ::GetCurrentThreadId() function that the ID of the calling thread is the same as the ID of thread that created that complex object. That verification fails for me, because the functions get called using the thread ID of the MAIN THREAD, that has the Main interface GUI.
Why is that? I cannot understand! (I hope I successfully explained myself).
The problem you seem to have, from your description at least, is that whatever external API you are using via CreateAnObject, it restricts its further use to creation thread. Taking it as is, you are limited to making calls from the creation thread only. Whenever your code running on other theads, including thread hosting CWarningDlg, needs to talk to this API, you need to transfer the call to the CActionDlg thread and proceed from there.
Synchronization can be SendMessage you already do, or something safer like PostMessage with event/message completion notification.
in the last hours I've struggled with delegates and accessing Windows Forms controls (C++) where I've used this tutorial (the first thread safe method): http://msdn.microsoft.com/en-us/library/ms171728.aspx#Y190
Changing TextBoxes and Labels works perfectly but when I want to show or hide the whole GUI from another thread this fails.
I use the following methode (which is part of the GUI class):
System::Void UI::showUI(boolean value) {
if (this->InvokeRequired) {
SetTextDelegate^ d = gcnew SetTextDelegate(this, &UI::showUI);
this->Invoke(d, gcnew array<Object^> { value });
} else {
if (value == true)
this->Show();
else
this->Hide();
}
}
In the first call the if-clause is true so Invoke is called. But usually the showUI method should be called a second time automatically where the if-clause returns false, but this is not happening. So the GUI is neither shown nor hiden.
Is it necessary to show/hide the GUI with a delegate or can I do it from every possible thread? If a delegate is necessary, why is showUI not executed a second time?
Thanks,
Martin
edit: okay the name SetTextDelegate is not appropriate but this is not the point...
This is a pretty standard case of deadlock, not uncommon with Control::Invoke(). It can only proceed if the UI thread is not busy. Use Debug + Windows + Threads and double-click the Main thread. Look at the call stack to see what it is doing. The typical case is that it is blocking, waiting for the thread to finish the job. That will never happen since the thread can't complete until the Invoke() call returns.
Don't block the UI thread.
Consider using BackgroundWorker, its RunworkerCompleted event is nice to do stuff after the thread completes, removing the need to block.
I have a GUI app that has a main thread and then I use NSOperation to run 2 other threads once the user clicks the Start button. Now one thread calculates a certain value and updates it. What I want thread 2 to do is to pick this value up and update the UI.
How do I get a IBOutlet Textfield value to get updated on the UI from this second thread ?
eg:
main.m --- handles the UI and has code to start the 2 threads when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
I am unable to accomplish the thread2.m task and update the UI. My issue is that how do I define a IBOutlet and update it with a value from thread2/1 so that the main.m has access to this value and updates the UI. I have access to the actual variable in main.m and can print it out using NSLog. Its just that I am getting stuck on how to update the UI with this value. As I need to have theIBOutlet in main.m to tie it with the UILabel in the app. Any ideas guys ? Thanks.
Could you add pointers to your thread1.m and thread2.m files? Then set them with either a constructor method or some accessor methods?
If I understand the situation you described in your example, and assuming what you are calculating is an int (you can modify as you need):
Add an accessor to thread1.m
-(int)showCurrentCalcValue
{
//Assume that you get calculatedValue from whereever else in your thread.
return calculatedValue;
}
Then add to thread2.m
NSTextField *guiTextField;
Thread1 *thread1;
-(void) setThread: (Thread1 *aThread)
{
self.thread1 = aThread;
}
-(void) setGuiTextField: (NSTextField *aTextField)
{
self.guiTextField = aTextField;
}
-(void) updateGUI()
{
[guiTextField setStringValue: [thread1 showCurrentCalcValue]];
}
Presuming your main.m is something like the following:
IBOutlet NSTextField *outputDisplay
-(void) setUpThreads()
{
Thread1 *thread1 = [[Thread1 alloc] init];
Thread2 *thread2 = [[Thread2 alloc] init];
[thread2 setGuiTextField: outputDisplay];
[thread2 setThread: thread1];
//Whatever else you need to do
}
Then just take care of setting everything and calling the methods in your threads.
Source code files don't matter. You could have all of this stuff in one file (not that that would be a good idea) and the problem would be unchanged. What matters are the classes.
Classes are not simply bags of code; you design them, you name them, and you define each class's area of responsibility. A class and/or instances of it do certain things; you define what those things are and aren't.
When writing NSOperation subclasses, don't worry about the threads. There's no guarantee they even will run on separate threads. Each operation is simply a unit of work; you write an operation to do one thing, whatever that may be.
eg: main.m --- handles the UI and has code to start the 2 threads —
operations
— when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
That's not one thing; that's an indefinite sequence of things.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
You should not touch the UI from (what may be) a secondary thread. See the Threading Programming Guide, especially the Thread Safety Summary.
I don't see why this should even be threaded at all. You can do all of this much more easily with an NSTimer running on the main thread.
If it would be inappropriate to “calculate… a particular value” on the main thread, you could make that an operation. Your response to the timer message will create an operation and add it to your computation queue. When the user hits stop, that action will go through on the main thread; invalidate the timer and wait for the queue to finish all of its remaining operations.
With either solution, “thread2.m” goes away entirely. Your update(s) to the UI will (and must) happen entirely on the main thread. With the latter solution, you don't even have to wait until you're done; you can update the UI with current progress information every time you receive the timer message.