Простой Поток 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