简单的C ++线程

时间:2009-02-27 20:05:54

标签: c++ multithreading winapi

我正在尝试用C ++(Win32)创建一个线程来运行一个简单的方法。我是C ++线程的新手,但对C#中的线程非常熟悉。这是我正在尝试做的一些伪代码:

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

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

我想从 MyMethod 调用 RunStuff 而不阻止它。在单独的线程上运行 RunStuff 的最简单方法是什么?

编辑:我还应该提一下,我希望将依赖项保持在最低限度。 (没有MFC ......等)

11 个答案:

答案 0 :(得分: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

答案 1 :(得分:7)

C ++ 11与更新的编译器(如Visual Studio 2013)一起提供,其中包含线程作为语言的一部分以及其他一些非常好的部分,例如lambdas。

包含文件threads提供了一组线程类,它是一组模板。线程功能位于std::命名空间中。一些线程同步函数使用std::this_thread作为命名空间(有关解释,请参阅Why the std::this_thread namespace?)。

使用Visual Studio 2013的以下控制台应用程序示例演示了C ++ 11的一些线程功能,包括使用lambda(请参阅What is a lambda expression in C++11?)。请注意,用于线程休眠的函数(例如std::this_thread::sleep_for())使用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;
}

答案 2 :(得分:4)

CreateThread (Win32)AfxBeginThread (MFC)是两种方法。

无论哪种方式,你的MyMethod签名都需要改变一下。

编辑:如评论和其他受访者所述,CreateThread可能不好。

_beginthread and _beginthreadex是C运行时库函数,根据文档等同于System::Threading::Thread::Start

答案 3 :(得分:3)

考虑使用Win32线程池,而不是为工作项启动新线程。旋转新线程是浪费的 - 默认情况下,每个线程为其堆栈获取1 MB的保留地址空间,运行系统的线程启动代码,导致通知几乎传递到进程中的每个DLL,并创建另一个内核对象。线程池使您能够快速有效地重用线程以执行后台任务,并根据您提交的任务数量增加或缩小。一般来说,考虑为永不停止的后台任务启动专用线程,并将线程池用于其他所有事务。

在Vista之前,您可以使用QueueUserWorkItem。在Vista上,新的线程池API更可靠,并提供了一些更高级的选项。每个都会导致您的后台代码开始在某个线程池线程上运行。

// 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);

答案 4 :(得分:2)

C ++中的简单线程是一个矛盾!

查看提升线程,了解最接近现有的简单方法。

对于最小答案(实际上并不能为您提供同步所需的所有内容,而是直接回答您的问题),请参阅:

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

同样static表示C ++中的不同内容。

答案 5 :(得分:1)

这是安全的吗?

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

_beginthread(myThread, 0, &data);

在此次通话后,我是否需要做任何事情来释放内存(如CloseHandle)?

答案 6 :(得分:1)

另一种选择是pthreads - 它们适用于Windows和Linux!

答案 7 :(得分:0)

  

CreateThread(Win32)和AfxBeginThread(MFC)是两种方法。

如果您需要使用C运行时库(CRT),请小心使用_beginthread。

答案 8 :(得分:0)

仅适用于win32且无需其他库即可使用 CreateThread函数 http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx

答案 9 :(得分:0)

如果你真的不想使用第三方库(我建议使用boost :: thread,如其他的anwsers中所述),你需要使用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;
}

答案 10 :(得分:0)

您可以使用许多开源跨平台C ++线程库:

其中包括:

Qt的
英特尔
TBB提升线程

您描述它的方式,我认为英特尔TBB或Boost线程都可以。

英特尔TBB示例:

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);

提升线程示例:
http://www.ddj.com/cpp/211600441

Qt例子:
http://doc.trolltech.com/4.4/threads-waitconditions-waitconditions-cpp.html
 (我认为这不符合您的需求,但只是为了完整而包含在这里;您必须继承QThread,实现void run(),并调用QThread :: start()):

如果您只在Windows上编程并且不关心跨平台,也许您可​​以直接使用Windows线程:
http://www.codersource.net/win32_multithreading.html