views:

992

answers:

11

I am trying to create a thread in C++ (Win32) to run a simple method. I'm new to C++ threading, but very familiar with threading in C#. Here is some pseudo-code of what I am trying to do:

static void MyMethod(int data)
{
    RunStuff(data);
}

void RunStuff(int data)
{
    //long running operation here
}

I want to to call RunStuff from MyMethod without it blocking. What would be the simplest way of running RunStuff on a separate thread?

Edit: I should also mention that I want to keep dependencies to a minimum. (No MFC... etc)

+1  A: 

Simple threading in C++ is a contradiction in terms!

Check out boost threads for the closest thing to a simple approach available today.

For a minimal answer (which will not actually provide you with all the things you need for synchronization, but answers your question literally) see:

http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx

Also static means something different in C++.

Daniel Earwicker
+9  A: 
static boost::thread runStuffThread();

static void MyMethod(int data)
{
    runStuffThread = boost::thread(boost::bind(RunStuff, data));
}

// elsewhere...
runStuffThread.join(); //blocks
greyfade
Do I need to worry about freeing any memory later if I create a thread like this? Are there any memory leaks by just doing this?
Jon Tackabury
This is an example using the boost library, not directly using the windows API. See http://stackoverflow.com/questions/596360/good-c-lib-for-threading for some info about boost and possibly other libraries to simplify threading in C++
Stephen Pape
boost::thread uses very few resources, all of which are cleaned up at application exit. It's also a lot easier to use than the CreateThread() functions or a pthread library.
greyfade
I would go with boost since it's cross-platform.
ssg
I *think* boost::thread itself is also a header-only library. It may, however, depend on linking to boost-system, but I can't remember off-hand.
greyfade
is this one of the ones scheduled for inclusion in the next version of C++ as part of the standard libraries? if so, it won't be an external dependency for long...
rmeador
This application will be long running, and will generate many threads. Will memory/resource cleanup be an issue? Does boost handle cleanup after the thread exits, or do I need to call something like CloseHandle for each thread?
Jon Tackabury
Thread creation will be standard in C++0x, and I think it will look something like this. Going with boost now might make it easier to port to C++0x later if desired.
Dan Olson
Why will the application create *many* threads?
Daniel Earwicker
It is an event handler, and receives notifications from other systems. Everytime it receives a notification I want to offload that work into a thread so that it doesn't block the caller.
Jon Tackabury
Thread *creation* is only as expensive as it is to request a thread handle. Cleanup is automatic on destruction of the boost::thread object.
greyfade
@Jon T - sounds like you need a pool of a limited number of worker threads all working from a queue. If you start an unlimited number of threads based on short-run demand, your program will perform badly under heavy load due to excessive context switching.
Daniel Earwicker
+3  A: 
crashmstr
IIRC, the CreateThread API is probably a bad idea, it doesn't initialize the CRT.
Daniel Earwicker
If you dynamically link to the CRT, CreateThread will cause the new thread to initialize the CRT in the thread attach message.
Michael
A: 

CreateThread (Win32) and AfxBeginThread (MFC) are two ways to do it.

Be careful to use _beginthread if you need to use the C run-time library (CRT) though.

rotoglup
beginthreadex is much more safe, because it guarantees for a quick exiting thread to not possibly return a handle to another thread, see remarks at http://msdn.microsoft.com/en-us/library/kdzttdcb(vs.71).aspx
jn_
A: 

For win32 only and without additional libraries you can use CreateThread function http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx

Mykola Golubyev
A: 

If you really don't want to use third party libs (I would recommend boost::thread as explained in the other anwsers), you need to use the Win32API:

static void MyMethod(int data)
{

    int data = 3;

    HANDLE hThread = ::CreateThread(NULL,
     0,
     &RunStuff,
     reinterpret_cast<LPVOID>(data),
     0,
     NULL);


    // you can do whatever you want here

    ::WaitForSingleObject(hThread, INFINITE);
    ::CloseHandle(hThread);
}

static DWORD WINAPI RunStuff(LPVOID param)
{  

     int data = reinterpret_cast<int>(param);

     //long running operation here

     return 0;
}
Edouard A.
This looks very close to what I need, but how would I call CloseHandle if I don't wait for the thread to complete?
Jon Tackabury
That comment that says "you can do whatever you want here" is a little misleading, isn't it? For a multi-threading program that actually has a chance of working, you should be quite careful about what you do there.
Daniel Earwicker
Jon T if you don't wait for thread completion you can close the Handle right away: you don't need it.
Edouard A.
And you should close it if you dont want a handles' leak ...
Eugenio Miró
+1  A: 

Is this safe:

unsigned __stdcall myThread(void *ArgList) {
//Do stuff here
}

_beginthread(myThread, 0, &data);

Do I need to do anything to release the memory (like CloseHandle) after this call?

Jon Tackabury
No - the compiler will take care of that for you.
Christopher Dolan
You need CloseHandle or _endthread to clean-up
crashmstr
How would I use CloseHandle if I just create this thread and it goes out of scope? I just want to start it and forget it about.
Jon Tackabury
The docs say that _endthread gets called automatically if the thread function extits
crashmstr
A: 
ShaChris23
A: 

Consider using the Win32 thread pool instead of spinning up new threads for work items. Spinning up new threads is wasteful - each thread gets 1 MB of reserved address space for its stack by default, runs the system's thread startup code, causes notifications to be delivered to nearly every DLL in your process, and creates another kernel object. Thread pools enable you to reuse threads for background tasks quickly and efficiently, and will grow or shrink based on how many tasks you submit. In general, consider spinning up dedicated threads for never-ending background tasks and use the threadpool for everything else.

Before Vista, you can use QueueUserWorkItem. On Vista, the new thread pool API's are more reliable and offer a few more advanced options. Each will cause your background code to start running on some thread pool thread.

// Vista
VOID CALLBACK MyWorkerFunction(PTP_CALLBACK_INSTANCE instance, PVOID context);

// Returns true on success.
TrySubmitThreadpoolCallback(MyWorkerFunction, context, NULL);

// Pre-Vista
DWORD WINAPI MyWorkerFunction(PVOID context);

// Returns true on success
QueueUserWorkItem(MyWorkerFunction, context, WT_EXECUTEDEFAULT);
Michael
A: 

More info about Treading

lsalamon
A: 

Another alternative is pthreads - they work on both windows and linux!

sean riley