Простой Поток C++

Я пытаюсь создать поток в C++ (Win32) для запуска простого метода. Я новичок в потоковой обработке C++, но очень хорошо знаком с потоковой обработкой в C#. Вот какой псевдо-код того, что я пытаюсь сделать:

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

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

Я хочу позвонить RunStuff С метод mymethod без его блокирования. Каков был бы самый простой способ бега RunStuff по отдельной теме?

Edit: Я должен также упомянуть, что я хочу сохранить зависимости до минимума. (Нет MFC... и т. д.)

11 ответов


#include <boost/thread.hpp>

static boost::thread runStuffThread;

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

// elsewhere...
runStuffThread.join(); //blocks

C++11, доступный с более поздними компиляторами, такими как Visual Studio 2013, имеет потоки как часть языка вместе с несколькими другими хорошими битами и частями, такими как lambdas.

файл threads предоставляет класс Thread, который представляет собой набор шаблонов. Функциональность потока находится в std:: пространство имен. Некоторые функции синхронизации потоков используют std::this_thread в пространстве имен (см. почему пространство имен std::this_thread? немного объяснение.)

в следующем примере консольного приложения с использованием Visual Studio 2013 демонстрируются некоторые функции потока C++11, включая использование лямбды (см. что такое лямбда-выражения в 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;
}

CreateThread (Win32) и AfxBeginThread (MFC) два способа сделать это.

в любом случае, ваша подпись MyMethod должна будет немного измениться.

Edit: как отмечено в комментариях и другими респондентами, CreateThread может быть плохим.

_beginthread и _beginthreadex являются функциями библиотеки времени выполнения C, и в соответствии с документами эквивалентны System::Threading::Thread:: Start


рассмотрите возможность использования пула потоков Win32 вместо создания новых потоков для рабочих элементов. Вращение новых потоков является расточительным - каждый поток по умолчанию получает 1 МБ зарезервированного адресного пространства для своего стека, запускает код запуска потока системы, заставляет уведомления доставляться почти в каждую DLL в вашем процессе и создает другой объект ядра. Пулы потоков позволяют быстро и эффективно использовать потоки для фоновых задач и будут расти или сокращаться в зависимости от количества задач представить. В общем, рассмотрите возможность вращения выделенных потоков для бесконечных фоновых задач и используйте threadpool для всего остального.

перед 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);

простой поток в C++ является противоречием в терминах!

Проверьте boost threads для ближайшей вещи к простому подходу, доступному сегодня.

для минимального ответа (который фактически не предоставит вам все, что вам нужно для синхронизации, но отвечает на ваш вопрос буквально) см.:

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

и static означает что-то другое в C++.


это безопасно:

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

_beginthread(myThread, 0, &data);

Мне нужно что-нибудь сделать, чтобы освободить память (например, CloseHandle) после этого вызова?


Другой альтернативой является pthreads не - они работают как на windows, так и на linux!


CreateThread (Win32) и AfxBeginThread (MFC) - два способа сделать это.

будьте осторожны, чтобы использовать _beginthread, если вам нужно использовать библиотеку времени выполнения C (CRT).


только для win32 и без дополнительных библиотек можно использовать Функция CreateThread http://msdn.microsoft.com/en-us/library/ms682453 (VS.85).aspx


Если вы действительно не хотите использовать сторонние библиотеки (я бы рекомендовал 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;
}

существует много кросс-платформенных библиотек потоков C++ с открытым исходным кодом, которые вы можете использовать:

среди них:

Qt
Корпорация Intel
TBB Boost thread

Как вы это описываете, я думаю, что либо Intel TBB, либо Boost thread будет в порядке.

пример Intel 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 example:
http://doc.trolltech.com/4.4/threads-waitconditions-waitconditions-cpp.html
(я не думаю, что это соответствует вашим потребностям, но просто включено здесь для полноты; вы должны наследовать QThread, реализовать void run () и вызвать QThread::start ()):

Если вы только программируете на Windows и не заботитесь о crossplatform, возможно, вы могли бы использовать поток Windows напрямую:
http://www.codersource.net/win32_multithreading.html