2015-08-16 1 views
3

Я хочу создать программу, где есть несколько потоков, единственное взаимодействие между потоками должно быть несколькими переменными, созданными только для передача между потоками. Одна из них будет очередью. Я хочу, чтобы один поток постоянно записывался в файл, и я хочу, чтобы другие потоки продолжали давать строки для записи.Создание потока внутри класса и его выполнение в funtion в классе в C++ (cpp)

Но для простоты я хочу, чтобы все это происходило от создания класса, а затем просто вызывало функцию, называемую give_line() из этого класса. Я хочу, чтобы этот поток записывал в файл, чтобы другие люди не могли возиться с ним.

class bar 
{ 
private: 
    std::queue<std::string> lines; // The queue 
    void write()      // The function we call from thread 
    { 
     std::cout << "Hello world from other thread"; 
    } 
public: 
    bar()        // constructor 
    { 
     std::thread writer(&bar::write, this);  // thread 
    } 
} 

int main() 
{ 
    bar testing; 
    std::cout << "Hello World from main thread" << std::endl; 

    /* 
    What this does is it allows me to keep the console open till we get a enter key. 
    */ 

    std::cin.clear(); 
    std::cin.ignore(32767, '\n'); 
    std::cin.get(); 


    return 0; 
} 

.

output: 
    Hello world from other thread 

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

Я понимаю, что мне нужен writer.join() где-то. Но это на потом. Я хочу, чтобы другая переменная смогла закончить все сразу. Эта переменная может быть доступна только из основного потока, поэтому другие потоки не могут справиться с ней. вроде как переменная kill_all.

+0

@DrewDormann: Ах да, вы правы. Это действительно убивает вашу программу. –

ответ

1

Здесь есть несколько проблем, но в первую очередь состоит в том, что конструктор std::thread выполняет функцию для запуска в недавно запущенном потоке. Похоже, вы не передаете функцию, вы проходите метод класса.

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

Вы, вероятно, пытался сделать что-то вроде этого:

static void invoke_write(bar *p) 
{ 
    p->write(); 
} 

bar() 
{ 
    std::thread writer(&invoke_write, this); 
} 

Теперь вы вызываете статическую функцию, и передавая ей указатель на класс инстанцировании, который используется для вызова метода класса.

Но настоящая причина, по которой вы врезаетесь, заключается в том, что вы создаете экземпляр std::thread внутри рамки конструктора bar.

И когда возвращается конструктор bar, объект std::thread, как и любой другой объект функции/метода, уничтожается, вызывая его деструктор. Но вы только что запустили поток, который запущен, и если вызывается деструктор std::thread, пока поток все еще запущен, вызывается terminate(), прерывая программу.

Вы должны join() перед уничтожением экземпляра std::thread, если поток работает. Так что, либо что-то вроде этого:

bar() 
{ 
    std::thread writer(&invoke_write, this); 

    writer.join(); 
} 

Или сделать Экземпляр std::thread члена класса, инстанцировании его в конструкторе, и присоединение к нему в деструкторе.Что-то вроде:

bar() : writer(&invoke_write, this) 
    { 
    } 

    ~bar() 
    { 
     writer.join(); 
    } 

private: 

    std::thread writer; 

Конечно, какой подход является правильным, это зависит от требований вашего приложения.

0

Простая замена вашего класса с кивком на @Sam Varchavchik заключается в том, чтобы вы не потеряли объекты потока сразу после его создания.

class bar 
{ 
private: 
    std::queue<std::string> lines; // The queue 
    std::thread writer; 

    void write()      // The function we call from thread 
    { 
     std::cout << "Hello world from other thread"; 
    } 
public: 
    bar() : writer{&bar::write, this} {} 

    ~bar() 
    { 
     writer.join(); 
    } 
}; 

Здесь поток конструктора инициализируется в конструкторе, и мы ждем его завершения в деструкторе.

Вы можете посмотреть немного измененную код, выполняемый здесь: http://ideone.com/Xf4dw5

Как уже упоминалось Сэм, ты не мог в пожилом C++ просто передать в метод класса для создания потока, так как он должен иметь объект, а также , Современный C++ позволяет это работать, связывая их вместе, как вы это сделали, передав «this» в конструктор потоков.

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