none
Зависает проект RRS feed

  • Вопрос

  • Всем доброго дря!

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

    Main.cpp

    #include<windows.h>
    #include<math.h>
    #include "Main.h"
    #include"resource.h"
    //Объявление глобальных переменных
    DWORD input_var[13]; // Массив входных переменных
    HANDLE event_obj[9]; // Массив хендлов объектов
                        //синхронизации
    HANDLE hThread[4]; // Массив хендловтредов
                      //Массив указателей на функции тредов
    LPTHREAD_START_ROUTINE pThread[4] =
    {
        (LPTHREAD_START_ROUTINE)Thread1,
        (LPTHREAD_START_ROUTINE)Thread2,
        (LPTHREAD_START_ROUTINE)Thread3,
        (LPTHREAD_START_ROUTINE)Thread4
    };
    //Хендл диалогового окна
    HWND hMainDlg;
    //Функция - первый тред
    void Thread1()
    {
        char buf[20];
        //Функцией addstr в ListBox выводится текст (см. main.h)
        addstr(#1: Starting thread ...);
        addstr(#1: b = b / c...);
        input_var[B] = input_var[B] / input_var[C];
        addstr(#1: Set event S14 ...);
        SetEvent(event_obj[S14]);
        addstr(#1: Sleep: (Waiting forS14) ...);
        //Функцияожиданияодногообъектасобытия
        WaitForSingleObject(event_obj[S14], INFINITE);
        addstr(#1: Restore: (S41 is setting up) ...);
        addstr(#1: f = f / d...);
        input_var[F] = input_var[F] * input_var[D];
        //Функция установки объекта события
        SetEvent(event_obj[S23]);
        addstr(#1: g = g + f...);
        input_var[G] = input_var[G] * input_var[F];
        SetEvent(event_obj[S13]);
        addstr(#1: Sleep: (Waiting forS43) ...);
        WaitForSingleObject(event_obj[S43], INFINITE);
        addstr(#1: Restore: (S43 is setting up) ...);
        // Вычисление результата с записью в переменную input_var[A]
        addstr(#1: A = a - m...);
        input_var[A] = input_var[A] - input_var[M];
        wsprintf(buf, "Result A = %li", input_var[A]);
        //Вывод результата нa экран (функция MessageBox)
        MessageBox(hMainDlg, buf, "Result", 0);
        addstr(#1: Exit thread ...);

        EnableWindow(GetDlgItem(hMainDlg, IDC_BUTTON1), true);
        EnableWindow(GetDlgItem(hMainDlg, IDC_BUTTON2), false);
    }
    void Thread2()
    {
        //Функция - второйтред
        addstr(#2: Starting thread ...);
        addstr(#1: d = d / e...);
        input_var[D] = input_var[D] / input_var[E];
        SetEvent(event_obj[S21]);
        addstr(#2: Sleep: (Waiting forS21) ...);
        WaitForSingleObject(event_obj[S31], INFINITE);
        addstr(#2: Restore: (S31 is setting up) ...);
        addstr(#4: h = h + d ...);
        input_var[H] += input_var[D];
        addstr(#2: Sleep: (Waiting forS13) ...);
        WaitForSingleObject(event_obj[S13], INFINITE);
        addstr(#2: Restore: (S13 is setting up) ...);
        addstr(#2: h = h / l ...);
        input_var[H] /= input_var[L];
        SetEvent(event_obj[S23]);
        addstr(#2: Exit thread ...);
    }
    void Thread3()
    {
        //Функция - третий тред
        addstr(#3: Starting thread ...);
        addstr(#1: i = i * j...);
        input_var[I] = input_var[I] * input_var[J];
        SetEvent(event_obj[S32]);
        addstr(#3: Sleep: (Waiting forS32) ...);
        WaitForSingleObject(event_obj[S41], INFINITE);
        addstr(#3: Restore: (S41 is setting up) ...);
        addstr(#3: f = f + b ...);
        input_var[F] -= input_var[B];
        addstr(#3: Sleep: (Waiting forS42) ...);
        WaitForSingleObject(event_obj[S42], INFINITE);
        addstr(#3: Restore: (S42 is setting up) ...);
        addstr(#3: g = g - h ...);
        input_var[G] -= input_var[H];
        addstr(#3: Exit thread ...);
    }
    void Thread4()
    {
        //Функция - четвертый тред
        addstr(#4: Startingthread ...);
        //При делении на 0 выводится сообщение
        //обошибке (функцияMessageBox)
        if (!input_var[M])
        {
            MessageBox(hMainDlg, "Divide by NULL error!\nRe enter some variables!", "Error", MB_ICONERROR);
            goto _ex;
        }
        addstr(#2: Restore: (S14 is setting up) ...);
        addstr(#2: a = sqrt(a) ...);
        //Вычисление квадратного корня
        input_var[A] =
            (DWORD)sqrt((double)input_var[A]);
        SetEvent(event_obj[S43]);
        addstr(#4: Sleep: (Waiting forS12) ...);
        WaitForSingleObject(event_obj[S12], INFINITE);
        addstr(#4: Restore: (S12 is setting up) ...)
        addstr(#4: h = h - k ...);
        input_var[H] -= input_var[K];
        SetEvent(event_obj[S42]);
        addstr(#4: Sleep: (Waiting forS23) ...);
        WaitForSingleObject(event_obj[S23], INFINITE);
        addstr(#4: Restore: (S23 is setting up) ...)
        addstr(#4: a = a + g ...);
        input_var[A] += input_var[G];
        SetEvent(event_obj[S43]);
    _ex:
        addstr(#4: Exitthread ...);
    }
    //Функция получения входных переменных
    bool GetOurVariables(HWND hDlg)
    {
        char varbuffer[10];
        for (int a = IDC_EDIT2; a <= IDC_EDIT14; a++)
        {
            input_var[a - IDC_EDIT2] = 0;
            if (!GetDlgItemText(hDlg, a, varbuffer, 10))
                return false;
            DWORD mul = 1;
            for (int b = lstrlen(varbuffer) - 1;
                b >= 0; b--, mul *= 10)
                input_var[a - IDC_EDIT2] +=
                (varbuffer[b] - 0x30) * mul;
        }
        return true;
    }
    //Процедураобработкидиалоговогоокна
    LRESULT CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        DWORD ThreadID; //ThreadID - уникальныйномертреда
                       //Обработкасообщений
        switch (uMsg)
        {
        caseWM_COMMAND:
            {switch (LOWORD(wParam))
            {
                //Обработка сообщения по нажатии
                //кнопки START
            caseIDC_BUTTON1:
                {
                    //Проверка введенных значений
                    if (!GetOurVariables(hDlg))
                    {
                        //Если данные не введены, то выводится сообщение (функция MessageBox)
                        MessageBox(hDlg, "Enter all variables and run again!", "Attention", MB_ICONINFORMATION);
                        return false;
                    }
                    //Функция отправки сообщения в ListBox (в данном случае очистка ListBox)
                    SendDlgItemMessage(hDlg, IDC_LIST1, LB_RESETCONTENT, 0, 0);
                    //Циклпосозданиютредов
                    for (int a = THREAD1; a <= THREAD4; a++)
                    {
                        //ЗаполнениемассиваhThreadхендламитредов
                        hThread[a] = CreateThread(NULL, NULL, pThread[a], NULL, NULL, &ThreadID);
                        //Установкаприоритетовтредов
                        SetThreadPriority(hThread[a], THREAD_PRIORITY_TIME_CRITICAL);
                    }
                    //Функции "активации деактивации" кнопок START и TERMINATE
                    EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), false);
                    EnableWindow(GetDlgItem(hDlg, IDC_BUTTON2), true);
                }
                break;
                //Обработка сообщения по нажатии кнопки TERMINATE
            caseIDC_BUTTON2: {
                //Цикл по принудительному завершению всех тредов (функция TerminateThread)
                for (int a = THREAD1;
                    a <= THREAD4; a++)
                {
                    TerminateThread(hThread[a], false);
                }
                //Функции "активациидеактивации" кнопок START и TERMINATE
                EnableWindow(GetDlgItem(hDlg, IDC_BUTTON2), false);
                EnableWindow(GetDlgItem(hDlg, IDC_BUTTON1), true);
                }
            }
            }
            break;
            //Обработка сообщения при создании диалогового приложения
        caseWM_INITDIALOG:
            {
                hMainDlg = hDlg;
                //Функцияотправкисообщения
                SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(0, IDI_EXCLAMATION));
            }
            break;
            //Обработка сообщения по нажатии кнопки CLOSE
        caseWM_CLOSE:
            //Функция завершения диалогового приложения
            EndDialog(hDlg, 0);
        }
        return false;
    }
    //Точка входа в программу
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        //Цикл по созданию объектов события функцией CreateEvent
        for (int a = S11; a <= S43; a++)
            event_obj[a] = CreateEvent(NULL, false, false, NULL);
        //Функциясозданиядиалоговогоокна
        DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, (DLGPROC)DlgProc, 0);
        return false;
    }
    Main.h

    #pragma once
    #ifndef MAIN_H
    #define MAIN_H
    #define A 0
    #define B 1
    #define C 2
    #define D 3
    #define E 4
    #define F 5
    #define G 6
    #define H 7
    #define I 8
    #define J 9
    #define K 10
    #define L 11
    #define M 12
    #define S11 0
    #define S12 1
    #define S13 2
    #define S14 2
    #define S21 4
    #define S22 5
    #define S23 6
    #define S24 7
    #define S31 8
    #define S32 9
    #define S33 10
    #define S34 11
    #define S41 12
    #define S42 13
    #define S43 14
    #define S44 15
    #define THREAD1 0
    #define THREAD2 1
    #define THREAD3 2
    #define THREAD4 3
    //Организация макроподстановки для вывода состояний тредов в ListBox
    //с помощью функции SendDlgItemMessage
    #define addstr(str) SendDlgItemMessage(hMainDlg, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM) #str); SendDlgItemMessage(hMainDlg, IDC_LIST1, LB_SETTOPINDEX, SendDlgItemMessage(hMainDlg, IDC_LIST1, LB_GETCOUNT, 0, 0) - 1, 0);
    void Thread1();
    void Thread2();
    void Thread3();
    void Thread4();

    Заранее блогадарю.

    2 апреля 2019 г. 12:55

Ответы

  • Здравствуйте.

    Странно, что оно вообще у Вас работает :)

    К сути. Зависаний не обнаружил, видимо это зависит от введенных в EDIT-ы данных. При этом хочу отметить несколько грубейших ошибок:

    1. Массив event_obj рассчитан на 9 элементов, а в WinMain производится попытка записи в него 15-ти значений. По "счастливой" случайности непосредственно за ним располагаются массивы hThread и pThread, которые и "принимают" дополнительные 6 значений. Но, поскольку содержимое этих массивов переписывается последующим кодом, дескрипторы 6-ти событий будут навсегда утеряны.

    2. Функция GetOurVariables рассчитывает на то, что у идентификаторов IDC_EDIT2 - IDC_EDIT14 значения заданы последовательно, однако это абсолютно не гарантировано (особенно, в случае последующего редактирования диалога).

    3. Функции потоков имеют неверную сигнатуру (void Имя()). Правильная сигнатура - DWORD WINAPI Имя (LPVOID). То, что Вы искусственно приводите указатели на функции, не гарантирует их правильный вызов и передачу параметра.


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    6 апреля 2019 г. 10:28