CreateThread() too slow

This is a discussion on CreateThread() too slow within the Windows Programming forums, part of the Platform Specific Boards category; Hi, I'm trying to create a basic multi-threading application in C++. The problem is CreateThread() is too slow. Worse still, ...

  1. #1
    Registered User
    Join Date
    Sep 2009
    Location
    US
    Posts
    6

    CreateThread() too slow

    Hi,
    I'm trying to create a basic multi-threading application in C++. The problem is CreateThread() is too slow. Worse still, it doesn't appear to halt my program while the new thread is created, the code after CreateThread() gets executed before the thread is ready. I use Beep() just for debugging purposes. My code is below:

    Code:
    #include <windows.h>
    #include <tlhelp32.h>
    
    DWORD WINAPI runThread(LPVOID args);
    bool isThreadReady = false;
    
    int main()
    {
    	DWORD dwGenericThread;
    	HANDLE hThread = CreateThread(NULL, 0, runThread, NULL, 0, &dwGenericThread);
    
    	if (isThreadReady == true)
    		Beep(523, 200);
    
    	CloseHandle(hThread);
    	return 0;
    }
    
    DWORD WINAPI runThread(LPVOID args)
    {
    	isThreadReady = true;
    	//Beep(523, 200);
    	return 0;
    }

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by Mimo View Post
    Worse still, it doesn't appear to halt my program while the new thread is created, the code after CreateThread() gets executed before the thread is ready.
    Well, yes.
    Quote Originally Posted by MSDN
    Synchronizing Execution of Multiple Threads (Windows)
    CreateProcess returns without waiting for the child process to complete its initialization.
    WaitForInputIdle is the suggestion on that same MSDN page.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    On a side note, you should use _beginthreadex in place of CreateThread in case you're using any CRT functions (to prevent memory leaks). At least that use to be the case, anyway.

  4. #4
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    After you call CreateThread all it has to do is return the HANDLE and do a simple boolean comparison. That's very very fast, so it's hardly that creating the thread is slow (which if the case, is one of the reasons thread pools are common place). Think about it asynchronously, CreateThread has to go through a fair amount of instructions along side your 1 line, which is faster? You could of course do it the correct way as suggested above, or the lazy way (if you're testing) would be to use Sleep(1000) or something. You might like the boost::thread interface more, although it probably just wraps CreateThread and in my case seems to act oddly sometimes.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I wonder if setting dwGenericThread to zero before creating the thread and then testing it in a loop afterwards would be sufficient? EDIT: Come to think of it, that probably won't work. Nevermind me...
    Last edited by Sebastiani; 09-03-2009 at 10:25 PM.

  6. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    As has been mentioned and recommended by Microsoft in their help for CreateThread() you should prefer to use _beginthread() or _beginthreadex().

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,308
    Quote Originally Posted by Mimo View Post
    Hi,
    I'm trying to create a basic multi-threading application in C++. The problem is CreateThread() is too slow. Worse still, it doesn't appear to halt my program while the new thread is created, the code after CreateThread() gets executed before the thread is ready. I use Beep() just for debugging purposes. My code is below:

    Code:
    #include <windows.h>
    #include <tlhelp32.h>
    
    DWORD WINAPI runThread(LPVOID args);
    bool isThreadReady = false;
    
    int main()
    {
    	DWORD dwGenericThread;
    	HANDLE hThread = CreateThread(NULL, 0, runThread, NULL, 0, &dwGenericThread);
    
    	if (isThreadReady == true)
    		Beep(523, 200);
    
    	CloseHandle(hThread);
    	return 0;
    }
    
    DWORD WINAPI runThread(LPVOID args)
    {
    	isThreadReady = true;
    	//Beep(523, 200);
    	return 0;
    }
    What you're really saying is that CreateThread is too fast, i.e. it returns before the thread it created has started executing any of its code. That's the way it's supposed to work. It isn't supposed to pause the current thread, wait for the new thread to be set up, perform a context switch to the new thread, run a certain number of lines of code, and perform another context switch back to the original thread. It would have a much longer name if it were supposed to do all of those things. Besides, it's not supposed to cause that kind of large performance hit. The whole point of threading is for different threads to do stuff at about the same time, so why should the original thread be made to wait?

    If you want to do all of that synchronisation stuff then you have to do it yourself. Typical method would be to use CreateEvent, WaitForSingleObject, and CloseHandle in the original thread and SetEvent in the spawned thread.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,189
    Quote Originally Posted by Mimo View Post
    The problem is CreateThread() is too slow.
    Worse still, ... the code after CreateThread() gets executed before the thread is ready.
    These two statements do not agree with one another.

    Createthread() only creates the thread, it doesn't immediately execute it. It schedules it for execution. You cannot assume that threads are synchronous, they are not, they are asynchronous. You need to use critical sections or MUTEX's to fix the behavior you mention.

    Oh, and createthread is as fast as you can possibly get. It executes in something like 30 instruction cycles. You are misperceiving ti as slow because your thread doesn't begin execution immediately. That has nothing to do with the speed of creatthread, it has to do with the task manager and how it schedules threads fro execution.
    Until you can build a working general purpose reprogrammable computer out of basic components from radio shack, you are not fit to call yourself a programmer in my presence. This is cwhizard, signing off.

  9. #9
    Registered User
    Join Date
    Sep 2009
    Location
    US
    Posts
    6
    Thanks for your help! I'm rather new to C++, I'm used to .NET doing my bidding for me. Anyway, I tried WaitForSingleObject; it seemed like the easiest solution to my problem. It worked great in my test application, but when I went to deploy it in my real application it froze. I forgot to mention that all of my code is done under DllMain. I read some reports that using WaitForSingleObject in a dll will cause a deadlock (which it did for me). For now I'm going to look into _beginthreadex, as I do use sprintf_s.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    WaitForSingleObject on a thread handle will wait for the thread to terminate, which is *not* what you want. (What's the point in creating a thread and then immediately blocking until it finishes? You might as well do the calculation in the origin thread.)

    The typical way to wait for a thread to have started is to use an event.
    Code:
    HANDLE g_initfinished;
    
    void threadfunc() // or whatever the correct prototype is
    {
      // do initialization
      SetEvent(g_initfinished); // signal that we're done initializing
      // do actual calculation
    }
    
    void creater()
    {
      g_initfinished = CreateEvent(/* params for an initially unsignaled event */);
      HANDLE thread = _beginthreadex(&threadfunc, ...);
      WaitForSingleObject(g_initfinished);
      // thread has finished initialization
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User
    Join Date
    Sep 2009
    Location
    US
    Posts
    6
    Thanks for your reply. I tried your code and it worked great in my test application, but unfortunately it caused a deadlock again. I found this this which states that what I am trying to do is impossible . Oh well, thank you all for your help .

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Why not just go back to the original design and loop on the flag?

    Code:
    #include <windows.h>
    #include <tlhelp32.h>
    
    DWORD WINAPI runThread(LPVOID args);
    bool isThreadReady = false;
    
    int main()
    {
    	DWORD dwGenericThread;
    	HANDLE hThread = CreateThread(NULL, 0, runThread, NULL, 0, &dwGenericThread);
    
    	while (!isThreadReady)
    		Sleep(0);
    
    	CloseHandle(hThread);
    	return 0;
    }
    
    DWORD WINAPI runThread(LPVOID args)
    {
    	isThreadReady = true;
    	//Beep(523, 200);
    	return 0;
    }
    EDIT:
    Also, I know it was just test code you posted, but you should never close a handle to a thread unless you know it's completed (use GetExitCodeThread and compare result with STILL_ACTIVE).
    Last edited by Sebastiani; 09-08-2009 at 08:02 PM.

  13. #13
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,702
    >> Why not just go back to the original design...
    Because it's incorrect, due to unsynchronized access to the same memory location.

    And because there is no "solution" when creating threads (or waiting for them to exit) within the context of DllMain - which is apparently what Mimo is doing.

    gg

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Codeplug View Post
    >> Why not just go back to the original design...
    Because it's incorrect, due to unsynchronized access to the same memory location.

    And because there is no "solution" when creating threads (or waiting for them to exit) within the context of DllMain - which is apparently what Mimo is doing.

    gg
    As I understood it he wasn't waiting for the thread to finish (which is only a problem because LoadLibraryXXX won't wait forever for DllMain to complete). And as far as unsynchonized access goes, I would normally agree, but in this case the flag (1) is initialized before the thread starts, (2) is only written to by the thread after the CreateThread call, (3) is a boolean value, so there is no problem with misinterpreted bit patterns. So it's a rare situation where synchonization really isn't necessary.

  15. #15
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,308
    Quote Originally Posted by Mimo View Post
    Thanks for your reply. I tried your code and it worked great in my test application, but unfortunately it caused a deadlock again. I found this this which states that what I am trying to do is impossible . Oh well, thank you all for your help .
    I shall quote part of the reply you linked to:
    If you find yourself needing to be able to wait on threads in DllMain, then your design is just not done correctly
    In addition though, the problem has nothing to do with WaitForSingleObject. It will not work like as you plan to do it no matter how you do your synchronisation.
    What you're doing is horribly broken; Find another way.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. CreateThread() function question
    By chiefmonkey in forum C++ Programming
    Replies: 5
    Last Post: 05-15-2009, 08:52 AM
  2. CreateThread and lpParam
    By Hunter2 in forum Windows Programming
    Replies: 6
    Last Post: 06-02-2004, 05:46 PM
  3. slow typing ad highlighting
    By axon in forum Tech Board
    Replies: 10
    Last Post: 01-13-2004, 08:27 PM
  4. slow game
    By lambs4 in forum Game Programming
    Replies: 2
    Last Post: 08-21-2003, 03:08 PM
  5. Solutions for slow performance?
    By Hunter2 in forum Game Programming
    Replies: 52
    Last Post: 08-24-2002, 11:04 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21