Get the TThread object for the currently executing thread? - multithreading

I want a function like GetCurrentThread which returns a TThread object of the current executing thread. I know there is a Win32 API call GetCurrentThread, but it returns the thread Id. If there is a possibility to get TThread object from that ID that's also fine.

From your own answer, it seems maybe you only want to "determine if running in the main thread or not", in which case you can just use
if Windows.GetCurrentThreadId() = System.MainThreadID then
// ...
Although this won't work from a DLL created with Delphi if it was loaded by a worker thread.

The latest version of Delphi, Delphi 2009, has a CurrentThread class property on the TThread class.
This will return the proper Delphi thread object if it's a native thread. If the thread is an "alien" thread, i.e. created using some other mechanism or on a callback from a third party thread, then it will create a wrapper thread around the thread handle.

I'm using my own TThread descendent that registers itself in a global list, protected with a lock.
That way, a method in this descendent can walk the list and get a TThread give an ID.

Answering my own question. I guess it is not possible to get TThread object from ID. It is possible by using a global variable. Then comparing its handle and current thread id, one can determine if running in the main thread or not.

Wouldn't the current executing thread be the one you're trying to run a function from?

You could store the pointer of the TThread instance in the current thread's context via the TlsSetValue API call and then retrieve it using TlsGetValue. However, note that this will only work if you're trying to retrieve/store the TThread instance of the current thread.

Related

What is the purpose of TThread.FinishThreadExecution, and when is it called?

I've been trying to implement a thread that runs in the background and updates a progress bar every second or so and following the example in the top answer to Delphi - timer inside thread generates AV. I notice that the proposed solution has an implementation of TThread.FinishThreadExecution. My IDE shows that my version of delphi supports that method, but I've been unable to find any documentation on it (google turns up 10 hits, none of which help, http://docwiki.embarcadero.com/ doesn't list that method under TThread. What is it for and when is it called?
FinishThreadExecution is not a method inherited from the TThread base class. It is only a method implemented in the derived class, TTimerThread.
The purpose of the method is to finish the execution of the thread in a proper way.
All FinishThreadExecution does is to call Terminate, which sets an internal flag in the TThread, plus sets the FTickEvent event to wake the thread. The thread execute method will then end and the thread will self destruct, since TThread.FreeOnTerminate is true.

COM object methods are not executed on the thread that CoInitialize-d and created the object

I am developing an UI application that creates a COM object along the way.
The problem is, I want to "move" this COM object entirely on a different thread.
What I do is this:
create the new thread I want to move the object into (with CreateThread API)
after entering this thread, I'm calling PeekMessage to setup a message queue for it
calling CoInitialize, CoCreateInstance to create the COM object, QueryInterface to get the interface I want
finally I call a method on the interface that displays a MessageBox with the value returned by GetCurrentThreadId() (I have access to the VB6 code of the COM library within which the object resides).
The problem is, as this message box shows, the object methods are still executed on the original UI thread, not on the thread I created and done all those steps into. One more thing to mention, after calling the interface method, I'm also setting up a classic message loop in it.
How can I change this behaviour and achieve what I want? (that is, I want the COM object calls that originate from my newly created thread to be executed ON IT, not on the original application thread)
Here's some pseudocode to make it even more clearer:
void myMainUIMethod(){
MessageBox(GetCurrentThreadId()); // displays 1
CreateThread(&myCOMObjectThreadProc);
}
void myCOMObjectThreadProc(){
MessageBox(GetCurrentThreadId()); // displays 2
CoInitialize(NULL);
myObject = CoCreateInstance(myObjectsCLSID);
myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
myObjectInterface->showThreadIDMessageBox(); // this would be the COM object method call
}
And, in the VB6 code of the object, here's the pseudo-definition of showThreadIDMessageBox.
Public Sub showThreadIDMessageBox()
Call MessageBox(GetCurrentThreadId()) //displays 1, I want it to display 2
End Sub
I have achieved what I wanted by CoUninitalizing on the main thread, before creating the new thread. But why does this happen? If COM was initialized ON THE MAIN THREAD before I'm creating the new thread, maybe for some reason it had to be..I would't want the application to crash later because I had to call CoUninitialize before creating my new thread. Here's some pseudocode that illustrates that whichever thread calls CoInitialize first will be the one picked by the STA objects.
void myMainUIMethod(){
MessageBox(GetCurrentThreadId()); // displays 1
CoUninitialize(); // uninitialize COM on the main thread
CreateThread(&myCOMObjectThreadProc);
***i: MessageBox("When you want to initialize COM on main thread, confirm this");
CoInitialize();
}
void myCOMObjectThreadProc(){
MessageBox(GetCurrentThreadId()); // displays 2
***ii: MessageBox("When you want to initialize COM on the new thread, confirm this");
CoInitialize(NULL);
myObject = CoCreateInstance(myObjectsCLSID);
myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
myObjectInterface->showThreadIDMessageBox(); // this shows 2 IF ***ii is confirmed before ***i, 1 otherwise
}
Thank you very much in advance,
Corneliu
Looks like your problem is that your COM component threading model is not specified in registry key InprocServer32. This means that object is considered as STA (single-threaded apartment) but will be loaded to main (or host) STA, not the STA that created it. This is the first thread that called CoInitialize. To be created in same STA that called CoCreateInstance you must create HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{Your CLSID}\InprocServer32#ThreadingModel registry value and set it to Apartment.
Quote from MSDN (InprocServer32 registry key documentation):
If ThreadingModel is not present or is not set to a value, the server is loaded into the first apartment that was initialized in the process. This apartment is sometimes referred to as the main single-threaded apartment (STA). If the first STA in a process is initialized by COM, rather than by an explicit call to CoInitialize or CoInitializeEx, it is called the host STA. For example, COM creates a host STA if an in-process server to be loaded requires an STA but there is currently no STA in the process.
I have finally achieved what I wanted! Adding a CoUninitialize call in the main UI thread, before creating the new thread has solved it. This happens because STA COM objects will be handled on the thread that first calls CoInitialize. Now all the calls to the objects methods are reported to be executed on the thread I created and the main window of the object (the COM component has a Form) is reported to belong to it too! (used WinSpy++ to test that).
There is still a question (and a problem) though..why does it behave this way?
Everywhere I search on the internet I see answers telling that a STA COM component will be fully executed on the thread it is created on (provided that CoInitialize or CoInitializeEx with COINIT_APARTMENTTHREADED had been called before), no matter what. Why does it matter if I called CoInitialize on another thread before..that's just plain stupid in my opinion for Microsoft to do so :), plus it might damage the future behaviour of my application, as I stated before.
EDIT: The correct answer is the one posted by Frost. Thank you again.
The threads are running in parallel and that's what they are meant to do. you need to synchronize between the two threads if you want one object to wait for some operation on other thread to complete. Event object will serve for your purpose.
You need to choose Free Threading as the Threading Model of the COM class when creating it. With C++ ATL, this is an option in the wizard when you select New -> COM class (or something like it). In .NET languages, I think this is specified as an attribute in the class.
BTW, you don't need to call QueryInterface after CoCreateInstance (unless you need more than one interface pointer). Just pass the GUID of the interface you want as the 4th parameter to CoCreateInstance.
Ah, I think I might know the problem now: it sounds like the VB6 COM object you are creating was registered as single-threaded, not apartment-threaded; this means that the object gets created on whichever thread is your app is the first to call CoInitialize().
This explain the behavior you are seeing: if you let your main thread CoInitialize() first, it becomes the "main thread" as far as COM is concerned, so the CoCreate ends up creating the object on it, even though it's CoCreated on a different thread. (This is only the case for single-threaded objects.)
But when you let your other thread CoInitialize() first, it is the "main thread" for COM, so the object gets created where you want it.
Can you change the threading model of your VB object to apartment instead of single? This would enable it to get created on the thread that calls CoCreate().
The problem is, I cannot change the threading model of the VB6 component since it is already used in other applications and it might damage it's behaviour.
...looks like that won't work for you. I guess you can check what the current threading model is, and if you can confirm that it's single, then you'll have an explanation for why it behaves the way it does, which might help you work with it.
--
So why does COM behave that way? - A: legacy compat issues. The Single Thread model is a holdover from before windows had threads in the first place, when every process had just one thread, and code didn't have to make any assumptions about synchronizations between objects within a process. To preserve this illusion and allow objects that were written assuming single-threaded COM to be used in a multithreaded environment, COM introduced the 'single' model, also known as 'legacy STA'. More details on this page, scroll down or search for "Legacy STA" for the details. COM basically puts all of these 'single' objects on the same [STA] thread - and uses whichever thread just happens to be the first to call CoInitialize. When you CoUninit and CoInit again on another thread, you're essentially restarting COM; so it's now the second thread that is the new "first thread to call CoInit", so that's why COM then ends up using that one...
(Legacy STA is such an old issue is was actually hard to track down any details; nearly all other articles mention apartment, free and both options; but there's rarely details about 'single'.)

Threads - Sharing variables

I have a system that is multi-threaded. I want to create a object in a thread, and every object that runs in this thread can view this object.
Example,
When i use GetCurrentThreadID i always get same id, if i call it from the same thread.
I want to call, for example, getSharedObject and always see the same object if i call it from the same object. So I need to write this object in a memory location that any object inside the same thread can see this object.
Is there anyway to do that, using the Windows API? Or I have to do it by myself?
thanks!
If the variable where you save the object pointer is global, then any code in your thread can access it. And any code from any other thread can, too, for that matter.
If you want that each thread sees a different object, then you want Thread Local Storage.
See the win32 functions TlsAlloc, TlsSetValue, TlsGetValue and TlsFree.
See also __declspec( thread ) here.

What is the difference between +[NSThread detachNewThreadSelector:toTarget:withObject:] and -[NSObject performSelectorInBackground:withObject:]?

They seem to perform a reasonably similar task: launching a new thread that performs that selector quickly and easily. But are there any differences? Maybe with regards to memory management?
Both are identical.
In iOS and Mac OS X v10.5 and later, all objects have the ability to spawn a new thread and use it to execute one of their methods. The performSelectorInBackground:withObject: method creates a new detached thread and uses the specified method as the entry point for the new thread. For example, if you have some object (represented by the variable myObj) and that object has a method called doSomething that you want to run in a background thread, you could could use the following code to do that:
[myObj performSelectorInBackground:#selector(doSomething) withObject:nil];
The effect of calling this method is the same as if you called the detachNewThreadSelector:toTarget:withObject: method of NSThread with the current object, selector, and parameter object as parameters. The new thread is spawned immediately using the default configuration and begins running. Inside the selector, you must configure the thread just as you would any thread. For example, you would need to set up an autorelease pool (if you were not using garbage collection) and configure the thread’s run loop if you planned to use it. For information on how to configure new threads
I presume they are the same, as - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; is defined in NSThread.h in the NSObject (NSThreadPerformAdditions) category. That is nothing conclusive, but that is evidence in that direction.

Is Gdiplus thread-safe?

I've perused the MSDN documentation and I couldn't find a statement one way or the other. What I'm interested in is:
Can I call GdiplusStartup() on one thread and then use Gdiplus on another thread? Or do I need to call GdiplusStartup() for each thread?
If I have a Bitmap object on thread 1 and different one on thread 2, can they both call Bitmap::DrawImage() at the same time, or do I need to add locking to ensure serialization?
Thanks.
Partial answer of question 2, according to MSDN - Security Considerations: GDI+:
Thread Synchronization
It is possible for more than one
thread to have access to a single GDI+
object. However, GDI+ does not provide
any automatic synchronization
mechanism. So if two threads in your
application have a pointer to the same
GDI+ object, it is your responsibility
to synchronize access to that object.
Some GDI+ methods return ObjectBusy if
a thread attempts to call a method
while another thread is executing a
method on the same object. Do not try
to synchronize access to an object
based on the ObjectBusy return value.
Instead, each time you access a member
or call a method of the object, place
the call inside a critical section, or
use some other standard
synchronization technique.
The MSDN documentation states 'You can call GdiplusStartup on one thread and call GdiplusShutdown on another thread', which would indicate that you only need to call GdiplusStartup() once for your process (and use it from any thread).
I'm not sure about question 2. (I think what you meant was can you call Graphics::DrawImage( bitmap ) at the same time?) You would create a different Graphics class in each thread, right? So there should be no problem.

Resources