Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Не срабатывает поток


Автор: rudolfninja 25.10.2013, 14:40
Доброго времени суток.
Сразу к вопросу:
Есть класс, в котором функцией run создается три потока. Потоки выполняют статические функции класса. В статическую функцию передается указатель на экземпляр класса, который вызвал ее, чтоб можно было получить доступ к общим объектам. Первый поток выводит в текстовое поле строку (разделяемый ресурс), второй - заменяет в нем одну букву на другую, третий - вторую на первую

Код

void MainWindow::run()
{
DWORD thread_id = -1;
_read_info_thread_handle = CreateThread(NULL, 0, &read_info, this, 0, &thread_id);
_a_to_b_thread_handle = CreateThread(NULL, 0, &a_to_b, this, 0, &thread_id);
_b_to_a_thread_handle = CreateThread(NULL, 0, &b_to_a, this, 0, &thread_id);
}

DWORD MainWindow::read_info(void* param)
{
    MainWindow* obj = (MainWindow*)param;
    if(!obj->get_is_buffer_exists()){
        obj->ui->log_text->append("Buffer is not exists!");
        return -1;
    }
    while(true)
    {
        QString curr_time = "[" + QTime::currentTime().toString("hh:mm:ss.zzz") + "] ";
        EnterCriticalSection(&obj->_cs);
        obj->ui->log_text->append(curr_time);
        obj->ui->log_text->append(obj->_buffer);
        LeaveCriticalSection(&obj->_cs);
        Sleep(200);
    }

    return 0;
}

DWORD MainWindow::a_to_b(void* param)
{
    MainWindow* obj = (MainWindow*)param;
    if(!obj->get_is_buffer_exists()){
        obj->ui->log_text->append("Buffer is not exists!");
        return -1;
    }
    while(true)
    {
        EnterCriticalSection(&obj->_cs);
        for(unsigned int i = 0; i < strlen(obj->_buffer); i++)
            if(tolower(obj->_buffer[i]) == 'a')
                obj->_buffer[i] = 'b';
        LeaveCriticalSection(&obj->_cs);
    }
    return 0;
}

DWORD MainWindow::b_to_a(void* param)
{
    MainWindow* obj = (MainWindow*)param;
    if(!obj->get_is_buffer_exists()){
        obj->ui->log_text->append("Buffer is not exists!");
        return -1;
    }
    while(true)
    {
        EnterCriticalSection(&obj->_cs);
        for(unsigned int i = 0; i < strlen(obj->_buffer); i++)
            if(tolower(obj->_buffer[i]) == 'b')
                obj->_buffer[i] = 'a';
        LeaveCriticalSection(&obj->_cs);
    }
    return 0;
}

После этого кода выводится только результат работы потока "б->а", результата "а->б" не видно.  Да и первый поток отрабатывает только определенное количество времени и потом перестает выполняться.
Не подскажете, в чем может быть проблема?

На всякий случай:
Код

class MainWindow : public QMainWindow
{
    Q_OBJECT
    HANDLE              _read_info_thread_handle;
    HANDLE              _a_to_b_thread_handle;
    HANDLE              _b_to_a_thread_handle;
    bool                _is_threads_created;
    bool                _is_buffer_exists;
    bool                _is_fileview_init;
    FileMapManager      _file_map_mng;
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    bool get_is_buffer_exists(){return _is_buffer_exists;}
    CRITICAL_SECTION    _cs;
    char*               _buffer;

private slots:
    void on_chose_file_button_clicked();
    void run();
private:
    Ui::MainWindow *ui;
    static DWORD WINAPI read_info(void* param);
    static DWORD WINAPI a_to_b(void* param);
    static DWORD WINAPI b_to_a(void* param);
};

Автор: Dem_max 25.10.2013, 14:56
Ну потому что такая конструкция
Код

    while(true)
    {
        EnterCriticalSection(&obj->_cs);


всегда будет вызывать дедлок для другого потока

Добавлено через 2 минуты и 53 секунды
На почитай от и до конца
http://wm-help.net/books-online/book/59464/59464-27.html#h8

Добавлено через 3 минуты и 41 секунду
http://wm-help.net/books-online/book/59464.html

Автор: xvr 27.10.2013, 19:55
Цитата(Dem_max @  25.10.2013,  14:56 Найти цитируемый пост)
всегда будет вызывать дедлок для другого потока

Ну сама по себе не будет, а вот то, что потоки 2 и 3 молотят без передыху вполне может вызвать замораживание всего на свете  smile 
2 ТС: Вставь как минимум Sleep(...) в потоки 2 и 3

Автор: rudolfninja 28.10.2013, 12:01
Основная проблема была в том, что не вызывался InitializeCriticalSection и DeleteCriticalSection.

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

Автор: GremlinProg 28.10.2013, 12:23
Цитата(rudolfninja @  28.10.2013,  14:01 Найти цитируемый пост)
Основная проблема была в том, что не вызывался InitializeCriticalSection и DeleteCriticalSection

а у Вас тут в коде реализации конструктора и нет, т.е. инициализации объекта класса MainWindow Вы нам и не показали,
стало быть, проблемного кода ни кто и не видел, а телепаты к нам заходят не часто )

Автор: Dem_max 29.10.2013, 07:02
Цитата(rudolfninja @ 28.10.2013,  12:01)
Основная проблема была в том, что не вызывался InitializeCriticalSection и DeleteCriticalSection.

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

Ты все таки почитай предложенную мной книгу.

Автор: rudolfninja 29.10.2013, 08:16
Цитата(Dem_max @  29.10.2013,  07:02 Найти цитируемый пост)
Ты все таки почитай предложенную мной книгу. 

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

Автор: GremlinProg 29.10.2013, 09:09
Не будет там дедлока, но время работы этих двух потоков будет "слабопрогнозируемо", т.к. один из них может вытеснять к выполнению другой. Это приведет к тому, что тот, который был вытеснен будет простаивать на какой-то итерации неопределенное время.

Из этого следует, что если какой-то "третий" поток будет опираться на результат работы вытесненного потока, то при синхронизации он будет вынужден так же простаивать. Сложится впечатление "дедлока".

А класс таких ошибок с дедлоком один.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)