Простой C ++ Threading - PullRequest
       21

Простой C ++ Threading

9 голосов
/ 27 февраля 2009

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

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

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

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

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

Ответы [ 11 ]

13 голосов
/ 27 февраля 2009
#include <boost/thread.hpp>

static boost::thread runStuffThread;

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

// elsewhere...
runStuffThread.join(); //blocks
7 голосов
/ 01 октября 2015

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

Включаемый файл threads предоставляет класс потока, который представляет собой набор шаблонов. Функциональность потока находится в пространстве имен 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;
}
4 голосов
/ 27 февраля 2009

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

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

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

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

3 голосов
/ 28 февраля 2009

Подумайте об использовании пула потоков Win32 вместо раскрутки новых потоков для рабочих элементов. Вращать новые потоки бесполезно: каждый поток по умолчанию получает 1 МБ зарезервированного адресного пространства для своего стека, запускает код запуска потока системы, вызывает доставку уведомлений почти во все библиотеки 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);
2 голосов
/ 27 февраля 2009

Простые потоки в C ++ противоречат друг другу!

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

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

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

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

1 голос
/ 16 марта 2009

Другая альтернатива - pthreads - они работают как на Windows, так и на Linux!

1 голос
/ 27 февраля 2009

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

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

_beginthread(myThread, 0, &data);

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

0 голосов
/ 27 февраля 2009

Существует много кроссплатформенных библиотек потоков 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:
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

0 голосов
/ 27 февраля 2009

Если вы действительно не хотите использовать сторонние библиотеки (я бы порекомендовал boost :: thread, как объяснялось в других приложениях), вам нужно использовать 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;
}
0 голосов
/ 27 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...