9

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)

Jon Tackabury
  • 42,888
  • 45
  • 121
  • 164
  • 3
    Simple c++ Threading. There is a joke in there somewhere. – jason saldo Feb 27 '09 at 20:19
  • LOL - I know, it's asking the impossible. By simple, I just meant that I'm not sharing any data between threads and don't need any locking. I just want to start the thread and forget about it. – Jon Tackabury Feb 27 '09 at 20:22

11 Answers11

13
#include <boost/thread.hpp>

static boost::thread runStuffThread;

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

// elsewhere...
runStuffThread.join(); //blocks
greyfade
  • 23,436
  • 7
  • 60
  • 78
  • 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 Feb 27 '09 at 20:10
  • 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 Feb 27 '09 at 20:12
  • 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 Feb 27 '09 at 20:14
  • I would go with boost since it's cross-platform. – Sedat Kapanoglu Feb 27 '09 at 20:14
  • 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 Feb 27 '09 at 20:18
  • 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 Feb 27 '09 at 20:20
  • 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 Feb 27 '09 at 20:20
  • 1
    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 Feb 27 '09 at 20:22
  • 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 Feb 27 '09 at 20:32
  • 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 Feb 27 '09 at 21:21
  • 1
    @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 Mar 02 '09 at 16:24
  • it'd be nice if you added the required boost header to your answer – User Jul 11 '12 at 20:39
7

C++11 available with more recent compilers such as Visual Studio 2013 has threads as part of the language along with quite a few other nice bits and pieces such as lambdas.

The include file threads provides the thread class which is a set of templates. The thread functionality is in the std:: namespace. Some thread synchronization functions use std::this_thread as a namespace (see Why the std::this_thread namespace? for a bit of explanation).

The following console application example using Visual Studio 2013 demonstrates some of the thread functionality of C++11 including the use of a lambda (see What is a lambda expression in C++11?). Notice that the functions used for thread sleep, such as std::this_thread::sleep_for(), uses duration from std::chrono.

// threading.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>

int funThread(const char *pName, const int nTimes, std::mutex *myMutex)
{
    // loop the specified number of times each time waiting a second.
    // we are using this mutex, which is shared by the threads to
    // synchronize and allow only one thread at a time to to output.
    for (int i = 0; i < nTimes; i++) {
        myMutex->lock();
        std::cout << "thread " << pName << " i = " << i << std::endl;
        // delay this thread that is running for a second.  
        // the this_thread construct allows us access to several different
        // functions such as sleep_for() and yield().  we do the sleep
        // before doing the unlock() to demo how the lock/unlock works.
        std::this_thread::sleep_for(std::chrono::seconds(1));
        myMutex->unlock();
        std::this_thread::yield();
    }

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    // create a mutex which we are going to use to synchronize output
    // between the two threads.
    std::mutex  myMutex;

    // create and start two threads each with a different name and a
    // different number of iterations. we provide the mutex we are using
    // to synchronize the two threads.
    std::thread myThread1(funThread, "one", 5, &myMutex);
    std::thread myThread2(funThread, "two", 15, &myMutex);

    // wait for our two threads to finish.
    myThread1.join();
    myThread2.join();

    auto  fun = [](int x) {for (int i = 0; i < x; i++) { std::cout << "lambda thread " << i << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } };

    // create a thread from the lambda above requesting three iterations.
    std::thread  xThread(fun, 3);
    xThread.join();
    return 0;
}
Community
  • 1
  • 1
Richard Chambers
  • 14,509
  • 3
  • 62
  • 86
4

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

Either way, your MyMethod signature would need to change a bit.

Edit: as noted in the comments and by other respondents, CreateThread can be bad.

_beginthread and _beginthreadex are the C runtime library functions, and according to the docs are equivalent to System::Threading::Thread::Start

crashmstr
  • 26,648
  • 8
  • 59
  • 77
3

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
  • 51,314
  • 5
  • 111
  • 139
2

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
  • 108,589
  • 35
  • 194
  • 274
1

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
  • 42,888
  • 45
  • 121
  • 164
1

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

sean riley
  • 2,495
  • 1
  • 20
  • 21
0

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
  • 5,034
  • 19
  • 37
  • 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 – newgre Feb 27 '09 at 20:22
0

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
  • 52,197
  • 14
  • 81
  • 101
0

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.
  • 6,058
  • 24
  • 31
  • 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 Feb 27 '09 at 20:19
  • 1
    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 Feb 27 '09 at 20:28
  • Jon T if you don't wait for thread completion you can close the Handle right away: you don't need it. – Edouard A. Mar 02 '09 at 09:41
0

There exists many open-source cross-platform C++ threading libraries you could use:

Among them are:

Qt
Intel
TBB Boost thread

The way you describe it, I think either Intel TBB or Boost thread will be fine.

Intel TBB example:

class RunStuff
{
public:
  // TBB mandates that you supply () operator  
  void operator ()()
  {
    // long running operation here
  }
};

// Here's sample code to instantiate it
#include <tbb/tbb_thread.h> 

tbb::tbb_thread my_thread(RunStuff);

Boost thread example:
http://www.ddj.com/cpp/211600441

Qt example:
http://doc.trolltech.com/4.4/threads-waitconditions-waitconditions-cpp.html
(I dont think this suits your needs, but just included here for completeness; you have to inherit QThread, implement void run(), and call QThread::start()):

If you only program on Windows and dont care about crossplatform, perhaps you could use Windows thread directly:
http://www.codersource.net/win32_multithreading.html

sivabudh
  • 29,317
  • 56
  • 156
  • 219