2014-08-27 8 views
18

Я попадаю в потоки C++ 11 и столкнулся с проблемой.Задержка начала потока в C++ 11

Я хочу объявить переменную потока как глобальную и начать ее позже.

Однако все примеры, которые я видел, кажется, запустить поток немедленно, например

thread t(doSomething); 

То, что я хочу

thread t; 

и запустить поток позже.

То, что я пытался это

if(!isThreadRunning) 
{ 
    thread t(readTable); 
} 

но теперь т является блок объема. Поэтому я хочу объявить t, а затем начать поток позже, чтобы t был доступен для других функций.

Спасибо за любую помощь.

+0

Как долго вы можете ждать? – billz

+1

'std :: this_thread :: sleep_for (std :: chrono :: milliseconds (x));' внутри потока? – Wikiii122

+0

^или используйте 'unique_ptr < thread >' и присвойте ему новый поток в точке, где он должен начинаться. Сказанное: globals в основном не одобряются. – stijn

ответ

0

Я бы дал нить условие переменной и логическое имя, которое называется startRunning (изначально установлено значение false). Эффективно вы должны начать поток сразу после создания, но первое, что он сделал бы, это приостановить себя (используя условие_вариабельный), а затем начать обработку своей фактической задачи, когда сигнализация condition_variable будет выдана извне (а флаг startRunning установлен в true).

РЕДАКТИРОВАТЬ: псевдокод:

// in your worker thread 
{ 
    lock_guard l(theMutex); 

    while (! startRunning) 
    { 
     cond_var.wait(l); 
    } 
} 

// now start processing task 


// in your main thread (after creating the worker thread) 
{ 
    lock_guard l(theMutex); 
    startRunning = true; 
    cond_var.signal_one(); 
} 

РЕДАКТИРОВАТЬ # 2: В приведенной выше коде, переменные theMutex, startRunning и cond_var должен быть доступным с обеими нитями. Достигаете ли вы этого, делая их глобальными или инкапсулируя их в экземпляр struct/class, зависит от вас.

+2

, если накладывает накладные расходы во время выполнения для создания потока, который никогда не будет использоваться – Anton

+0

@Anton Да, это так, но тогда я не удивлюсь, если ваше решение не приведет к подобным накладным расходам во время выполнения. Динамические распределения памяти также не так дешевы. – antred

+0

Я имел в виду, что, несмотря на решение создать или не создать, в этом подходе вам придется заплатить за создание потока (и, кроме того, за синхронизацию). Распределение памяти намного дешевле, чем создание потоков, и мой ответ включает в себя строительство на месте, которое полностью бесплатное – Anton

0

Вы можете использовать singleton pattern. Или я бы сказал: antipattern.

Внутри синглтона у вас будет std::thread объект инкапсулирован. При первом доступе к singleton ваш поток будет создан и запущен.

+0

Зачем вам предлагать что-то, что вы уже признали анти-шаблоном? Существует очень, очень мало оправданных видов использования однотонных, и это не один из них. – antred

+2

@antred, потому что он решает проблему, которая уже имеет все недостатки singleton (т.е. объект глобальной нити)? – GreenScape

25

std::thread По умолчанию конструктор создает экземпляр std::thread без запуска или представления фактической темы.

std::thread t; 

Оператор присваивания перемещает состояние объекта потока, и устанавливает назначенный-от объекта потока его по умолчанию инициализируется состояние:

t = std::thread(/* new thread code goes here */); 

Это первый строит временный объект потока, представляющий новый thread, переносит новое представление потока в существующий объект потока, который имеет состояние по умолчанию, и устанавливает состояние состояния временного потока в состояние по умолчанию, которое не представляет ни одного работающего потока. Затем временный объект потока уничтожается, ничего не делая.

Вот пример:

#include <iostream> 
#include <thread> 

void thread_func(const int i) { 
    std::cout << "hello from thread: " << i << std::endl; 
} 

int main() { 
    std::thread t; 
    std::cout << "t exists" << std::endl; 

    t = std::thread{ thread_func, 7 }; 
    t.join(); 

    std::cout << "done!" << std::endl; 
} 
0

Там нет «стандарт» в создании потока «приостановлено», который я предполагаю, что вы хотите делать с библиотекой потоков в C++. Поскольку он не поддерживается на каждой платформе, имеющей потоки, ее нет в C++ API.

  1. Возможно, вы захотите создать класс со всеми требуемыми данными, но не на самом деле запустить свою функцию потока. Это не то же самое, что создавать поток, но может быть тем, что вы хотите. Если это так, создайте это, а затем свяжите объект и его функцию operator() или start() или что-то в этом потоке.

  2. Возможно, вам понадобится идентификатор потока для вашей темы. Это означает, что вам действительно нужно запустить функцию потока. Однако он может начинаться с ожидания переменной состояния. Затем вы передаете или передаете эту переменную условия позже, когда хотите продолжить ее выполнение. Конечно, вы можете проверить функцию после того, как она возобновится, если вы, возможно, решили закрыть ее и не запустить ее в конце концов (в этом случае она просто вернется сразу).

  3. Возможно, вам нужен объект std::thread без функции. Вы можете сделать это и прикрепить его к функции позже до run, которые работают в новом потоке.

+0

«Он не поддерживается на каждой платформе» просто фиктивный. 'std :: thread' - это стандартная структура данных библиотеки.Независимо от того, является ли связанная функция 'run()' неявным или явным образом на усмотрение стандарта. –

Смежные вопросы