2015-04-06 8 views
0

Есть ли способ остановить и начать тему? Я хочу, чтобы пользователь мог остановить и запустить функцию по своему усмотрению. например:Остановить, и начать поток?

void func() 
{ 
while (1) 
{ 
cout << "I am a function!" << endl; 
} 
} 

void stopfunc(); 
{ 
if (condition...) 
t1.stop(); (???) 
} 
} 

int main() 
{ 
thread t1(func); 
thread t2(stopfunc) 

t1.join(); 
t2.join(); 
} 

EDIT: Я попробовал то, что кто-то в комментариях предложил, это не сработало:

atomic<bool> stop_func{ false }; 

    void toggle() 
    { 
     while (1) 
     { 
      Sleep(20); 

      if (GetAsyncKeyState(VK_F6)) 
      { 
       stop_func = true; 
      } 
     } 
    } 

    int Func() 
    { 
     while (!stop_func) 
     { 
      HWND h = FindWindow(NULL, "...."); 

      if (!process->Attach("...")) 
       return 1; 

      Interface::OnSetup(); 
      Static::OnSetup(); 
      Dynamic::OnSetup(); 

      if (!g_pOverlay->Attach(h)) 
       return 2; 

      g_pRenderer->OnSetup(g_pOverlay->GetDevice()); 

      hFont = g_pRenderer->CreateFont("Verdana", 12, FONT_CREATE_SPRITE | FONT_CREATE_OUTLINE | FONT_CREATE_BOLD); 

      g_pOverlay->AddOnFrame(OnFrame); 

      return g_pOverlay->OnFrame(); 
     } 
    } 

    int main() 
    { 
    thread t1(Func); 
    thread t2(toggle); 

    t1.join(); 
    t2.join(); 
} 

Что я делаю неправильно?

+1

Простой способ сделать это - установить флаг и периодически проверять другой поток. Убедитесь, что вы используете атомные операции. Без какого-либо сотрудничества с остановленной нитью это невозможно в стандартном C++ и по уважительным причинам. –

+0

Не могли бы вы уточнить, что вы подразумеваете под флагом? – michealbell

+1

'std :: atomic stop_func {false}; void func() {while (! stop_func) {...}} void stopfunc() {stop_func = true; } ' –

ответ

0

Не существует прямого, портативного способа запуска или остановки потока.

Вы можете прийти довольно близко, установив флаг, и имеющий выход резьбы, когда/если флаг установлен:

class foo { 
    std::atomic<bool> flag; 
public: 
    void pause() { flag = true; } 
    void unpause() { flag = false; } 

    void operator() { 
     for (;;) { 
      if (flag) yield(); 
      _do_other_stuff(); 
     } 
    } 
}; 

Если вам действительно нужна нить, чтобы полностью остановить, вы можете использовать native_handle, чтобы получить встроенный дескриптор потока. Затем, поскольку вы, по-видимому, пишете для Windows, вы можете использовать, вы можете использовать SuspendThread и ResumeThread, чтобы действительно приостановить и возобновить поток, но, конечно, код кода, который делает это, не будет переносимым.

+1

Это не просто проблемы с переносимостью. Подвешенный поток может содержать мьютекс, потенциально приводящий к тупиковой ситуации или в середине изменения некоторой структуры данных, оставляя ее в несогласованном состоянии и т. Д. –

+0

@TC: Пока поток, выполняющий приостановление, не удерживать любой мьютекс (или семафор и т. д.), когда он приостанавливает другой поток, а остальная часть кода использует синхронизацию правильно, приостановка потока довольно безопасна. Другие потоки, зависящие от этого, тоже могут заглохнуть, но это не должно привести к тупиковой ситуации. –

+0

'void thread1() {new int; } void thread2() {suspend (thread1); новый int; резюме (thread1); } 'может определенно затормозить, если thread1 приостановлен, когда он удерживает блокировку кучи. –