Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.88/25: Рейтинг темы: голосов - 25, средняя оценка - 4.88
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915

А можно ли дождаться выполнения CreateThread ?

17.10.2019, 20:57. Показов 6062. Ответов 59
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте,

Решил немного с в winapi поиграться и понял, что мало че понимаю

Вот взял самую простую функцию CreateThread:

C++
1
2
3
4
5
6
7
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES   lpThreadAttributes,
SIZE_T                  dwStackSize,
LPTHREAD_START_ROUTINE  lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD                   dwCreationFlags,
LPDWORD                 lpThreadId);
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void my_function1(int &i)
{
    i++;
}
 
int main()
{
 
    int i = 1;
    int y = 3;
 
    HANDLE handle_thread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) my_function1, (LPVOID)(&i), NULL, NULL);
 
    cout << handle_thread << endl;
 
    cout << i << endl;
}

Вот к примеру несколько вопросов:

1)Как в функцию my_function1 через CreateThread передать более одно параметра ?
2)Почему, если нужно передать параметр по ссылке, то в CreateThread (&i), ведь когда просто в C++ передаешь по ссылке, то так делать не нужно, только указать в приемной функции, что функция принимает параметр по ссылке, а не по значению.
3)И можно ли дождаться в какой то точке выполнения CreateThread ? По идее можно, ведь в std:thread это как т о реализовано.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.10.2019, 20:57
Ответы с готовыми решениями:

Дождаться выполнения процедуры
Доброго времени суток! Есть таймер, в котором постоянно выполняется 30 процедур. Одна из процедур является ресурсоемкой, если точнее, то...

Promise, как дождаться выполнения
Здравствуйте. Есть код, у меня вместо setTimeout идет запись в indexedDB, но это не должно менять суть вещей. console.clear(); ...

Дождаться выполнения обработки страницы
Всем привет, ребят :victory: Есть функция, которая парсит сайт и затем записывает нужную инфу в DataGridView. На моем компьютере все...

59
Эксперт С++
 Аватар для _lunar_
3701 / 2836 / 451
Регистрация: 03.05.2011
Сообщений: 5,193
Записей в блоге: 21
22.10.2019, 21:59
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Optimus11 Посмотреть сообщение
зачем перед ней ставить LPTHREAD_START_ROUTINE и почему в скобках, почему без скобок не работает
это называется приведение типов.
вы хоть прототип функции видели?
C++
1
2
3
4
5
6
7
8
9
10
11
12
WINBASEAPI
_Ret_maybenull_
HANDLE
WINAPI
CreateThread(
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ SIZE_T dwStackSize,
    _In_ LPTHREAD_START_ROUTINE lpStartAddress,
    _In_opt_ __drv_aliasesMem LPVOID lpParameter,
    _In_ DWORD dwCreationFlags,
    _Out_opt_ LPDWORD lpThreadId
    );
третий параметр LPTHREAD_START_ROUTINE lpStartAddress
LPTHREAD_START_ROUTINE это тип, который нужно передать в функцию CreateThread
вы передаёте же остальные параметры размер стека, DWORD и прочее, тоже самое и здесь.

Цитата Сообщение от Optimus11 Посмотреть сообщение
LPVOID - это что то типа указателя
void это грубо говоря общий тип.
как таковой его использовать не имеет смысла, поэтому обычно его приводят к необходимому типу.

Цитата Сообщение от Optimus11 Посмотреть сообщение
пытаюсь передать указатель на string i --- (LPVOID)i
честно говоря, ваш код та ещё хе..ня
вы поставьте задачу в виде текста, а не пытайтесь отобразить её в коде, у вас это не получается.
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
22.10.2019, 22:07
Цитата Сообщение от Optimus11 Посмотреть сообщение
только не понимаю зачем перед ней ставить LPTHREAD_START_ROUTINE и почему в скобках, почему без скобок не работает.
Без скобок не работает, потому что ты её неправильно объявил - надо DWORD WINAPI my_function2

Добавлено через 1 минуту
И не надо перед ней ставить (LPTHREAD_START_ROUTINE), должно компилироваться без этого

Добавлено через 3 минуты
Цитата Сообщение от Optimus11 Посмотреть сообщение
- и еще не моvtyn понять этот момент: int* a = (int*)Param; в самой функции my_function2 создали указатель и int* a и присваиваем переданный функию указатель, не могу понять, что значит запись (int*), почему нельзя просто int* a = (int*)Param, ведь Param - это уже указатель ?
Просто так короче получается его использовать, чем каждый раз делать (int*)Param -
как-то a[0] выглядит лучше, чем ((int*)Param)[0]

Добавлено через 3 минуты
Цитата Сообщение от Optimus11 Посмотреть сообщение
2)Почему, если нужно передать параметр по ссылке, то в CreateThread (&i), ведь когда просто в C++ передаешь по ссылке, то так делать не нужно, только указать в приемной функции, что функция принимает параметр по ссылке, а не по значению.
CreateThread - это не с++, это си, там ссылок не было.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
22.10.2019, 22:47  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Без скобок не работает, потому что ты её неправильно объявил - надо DWORD WINAPI my_function2

Добавлено через 1 минуту
И не надо перед ней ставить (LPTHREAD_START_ROUTINE), должно компилироваться без этого.
Да, правда, word на dword изменил, заработало.
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
23.10.2019, 19:14  [ТС]
Получается передать более одного аргумента можно только через struct ?

Делаю так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
DWORD WINAPI my_function4(LPVOID Param2)
{
    cout <<"Структура:"<< ((string*)Param2)[0] << endl;    // но тут ошибки ведь нет 
    cout << "Структура:" << ((int*)Param2)[1] << endl;    // но тут ошибка, выражение должно иметь тип указателя на объект
 
    return 0;
}
 
 
int main()
{
 
    setlocale(LC_ALL, "Russian");
  
    string i = "1";
    int y = 3;
 
    struct my_struct
    {
        string f1;
        int f2;
    };
 
 
    my_struct Structura;
    Structurka.i = i;
    Structurka.f2 = y;
    
    HANDLE handle_thread2 = CreateThread(NULL, NULL, my_function4, (LPVOID)&Structura, NULL, NULL);
 
 
    WaitForSingleObject(handle_thread2, INFINITE);
Как в самой функции куда был передан указатель на структуру, обращатся к переменный этой структуры ?
0
2846 / 1707 / 273
Регистрация: 19.02.2010
Сообщений: 4,488
23.10.2019, 20:03
Лучший ответ Сообщение было отмечено Optimus11 как решение

Решение

Цитата Сообщение от Optimus11 Посмотреть сообщение
Как в самой функции куда был передан указатель на структуру, обращатся к переменный этой структуры ?
Объявление типа (структуры) сделать глобальным - а не внутри функции майн/ВинМайн. Чтобы и внутри функции потока было видно этот тип.

Далее просто приводите аргумент к указателю на тип-структуру, и явно обращайтесь к именам полей:
C
1
2
3
4
5
6
DWORD WINAPI my_function4(LPVOID Param2)
{
    my_struct *s=(my_struct *)Param2;
    cout <<"Структура:"<< s->f1 << endl;
    cout <<"Структура:"<< s->f2 << endl;
}
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
23.10.2019, 20:35  [ТС]
Работает.
А другоо способа, как передать переменную в функцию помимо структуры нет ? Просто получается, что есть в main переменная которую я хочу передать string i, я создаю структуру, присваиваю элементу структуры значение этой переменной, и когда уже в функции меняю значение, то меняется значение не переменной string i, а элемента структуры f1, а надо чтобы переменной
То есть нужно по завершению потока, присваивать значения string i = Structura.f1. Этож неудобно.
В std::thread как то ведь это реализоаано. Мли там примерно так и реализовано может, только скрыто.
0
2846 / 1707 / 273
Регистрация: 19.02.2010
Сообщений: 4,488
23.10.2019, 21:01
Цитата Сообщение от Optimus11 Посмотреть сообщение
а надо чтобы переменной
Так и передавать тогда адрес этой переменной.
Если надо менять значения нескольких переменных - то предварительно в передаваемую в поток структуру не их значения копировать, а адреса (чтобы иметь возможность затем менять данные в "исходных" областях памяти, а не в их копиях). Т.е. структурный тип создавать из указателей.
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.10.2019, 22:12
Цитата Сообщение от Optimus11 Посмотреть сообщение
В std::thread как то ведь это реализоаано. Мли там примерно так и реализовано может, только скрыто.
Там это сделано примерно вот так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
template <typename TFunc>
unsigned ThreadProc(void *arg)
{
    std::unique_ptr<TFunc> sp(reinterpret_cast<TFunc *>(arg));
    (*sp)();
    return 0;
}
 
template <typename TFunc, typename... TT>
HANDLE create_thread(TFunc &&func, TT&&... args)
{
    auto fn = [func = std::move(func), ...args = std::move(args)]()
    {
        std::invoke(std::move(func), std::move(args)...);
    };
    using T = decltype(fn);
    std::unique_ptr<T> sp(new T(std::move(fn)));
    HANDLE h = (HANDLE)_beginthreadex(nullptr, 0, ThreadProc<T>, sp.get(), 0, nullptr);
    if (h)
        sp.release();
    return h;
}
 
int main()
{
        std::string s = __FUNCTION__;
        std::cout << s << std::endl;
        auto h = create_thread([&s]()
        {
            s = __FUNCTION__;
        });
 
        ::WaitForSingleObject(h, INFINITE);
        std::cout << s << std::endl;
        ::CloseHandle(h);
         return 0;
}
0
Эксперт С++
 Аватар для _lunar_
3701 / 2836 / 451
Регистрация: 03.05.2011
Сообщений: 5,193
Записей в блоге: 21
24.10.2019, 14:44
Цитата Сообщение от Optimus11 Посмотреть сообщение
Получается передать более одного аргумента можно только через struct ?
не обязательно.
в функции, передаваемой параметры в поток, могут быть несколько аргументов.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
24.10.2019, 19:15  [ТС]
Цитата Сообщение от _lunar_ Посмотреть сообщение
не обязательно.
в функции, передаваемой параметры в поток, могут быть несколько аргументов.
Функция передаваяемая параметры в поток, Вы имеете ввиду CreateThread или какую то другую функцию ?
0
Эксперт С++
 Аватар для _lunar_
3701 / 2836 / 451
Регистрация: 03.05.2011
Сообщений: 5,193
Записей в блоге: 21
27.10.2019, 12:58
Цитата Сообщение от Optimus11 Посмотреть сообщение
Вы имеете ввиду CreateThread или какую то другую функцию ?
вся суть создания потоков заключается в 2 вещах:
- определение базового адреса (откуда будет начинаться исполнение потока) LPTHREAD_START_ROUTINE lpStartAddress
- передаваемые параметры в поток LPVOID lpParameter (необязательно если функция потока исполняется сразу в коде программы)
LPVOID lpParameter может иметь несколько аргументов, например
C++
1
2
ULONG_PTR lParam(int arg1, char *arg2, ...)
   return SomeFunction(arg1, &arg2, ...);
CreateThread сводится к созданию удаленного потока (тот в свою очередь вызывает NTCreateThread).

поток создаётся в 2 случаях:
- в собственном процессе (приложении) для выполнения разных задач по оптимизации приложения (например, когда читается большой файл или отображается в память, а приложение имеет интерфейс, чтобы не зависал GUI целесообразно чтение этого файла проводить в отдельном потоке)
- внедрение своего потока в чужой процесс с целью исполнения некоторого кода, тогда
C++
1
2
3
4
5
6
CreateProcess(
   ...
   (LPTHREAD_START_ROUTINE)BaseAddr,
   (LPVOID)lParam(arg1, &arg2, ...),
   ...
);
2
2 / 2 / 0
Регистрация: 08.10.2019
Сообщений: 11
27.10.2019, 18:13
Цитата Сообщение от Optimus11 Посмотреть сообщение
В функцию Createthread передаю my_function2, только не понимаю зачем перед ней ставить LPTHREAD_START_ROUTINE и почему в скобках, почему без скобок не работает.
можно вроде и без этого, вот пример https://docs.microsoft.com/ru-... dfrom=MSDN
1
фрилансер
 Аватар для Алексей1153
6495 / 5724 / 1133
Регистрация: 11.10.2019
Сообщений: 15,286
27.10.2019, 18:47
Alexei55555,

в тёмных глубинах WinAPI есть такие определения
C++
1
2
3
4
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(
    LPVOID lpThreadParameter
    );
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
если твоя функция уже имеет тип LPTHREAD_START_ROUTINE , то явное приведение не нужно. А если тип другой, то, скорее всего, будет краш
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
27.10.2019, 18:51  [ТС]
Цитата Сообщение от Alexei55555 Посмотреть сообщение
можно вроде и без этого, вот пример https://docs.microsoft.com/ru-... dfrom=MSDN

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

Добавлено через 2 минуты
Подскажите пожалуйста, а можно ли создать CreateThread и после выполнения ее функции, чт юы поток не удалился, а чтобы остался в неактивном состоянии, что бы него в этот поток можно было передать другую функцию, чтобы не тратииь время процессора на создание нового потока ?
0
фрилансер
 Аватар для Алексей1153
6495 / 5724 / 1133
Регистрация: 11.10.2019
Сообщений: 15,286
27.10.2019, 18:54
Optimus11, конечно можно, просто вызови другую функцию


Цитата Сообщение от Optimus11 Посмотреть сообщение
чтобы не тратииь время процессора
а вот это ещё надо суметь доказать, что оно как-то влияет на производительность
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
27.10.2019, 18:57  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Optimus11, конечно можно, просто вызови другую функцию
А какую ?
Цитата Сообщение от Алексей1153 Посмотреть сообщение
а вот это ещё надо суметь доказать, что оно как-то влияет на производительность
Ну так, если не все, то большинство пишут, что на создание потока уходит много инструкций, и чтобы как то это минимизировать и делают пул потоков, что бы их переиспользовать
0
Эксперт С++
 Аватар для _lunar_
3701 / 2836 / 451
Регистрация: 03.05.2011
Сообщений: 5,193
Записей в блоге: 21
28.10.2019, 10:50
Цитата Сообщение от Optimus11 Посмотреть сообщение
на создание потока уходит много инструкций
да это верно.
создание процессов и потоков - одни из самых масштабных internal-функций.
но учитывая качественные и количественных технологии современных процессоров экономить ресурсы не имеет смысла, всё происходит за ничтожные доли секунды.
2
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
28.10.2019, 11:02
Цитата Сообщение от Optimus11 Посмотреть сообщение
Ну так, если не все, то большинство пишут, что на создание потока уходит много инструкций, и чтобы как то это минимизировать и делают пул потоков, что бы их переиспользовать
Правильно пишут. Лучше потоки создавать заранее, а не в момент, когда тебе нужно обработать задачу.
И здесь не только вопрос производительности - создание потока, это операция, которая может вызвать исключение (т.е. поток может не создастся), соответственно твой алгоритм должен будет как-то реагировать на это.
Пул потоков - тоже не таблетка от всех болезней. Во-первых, количество потоков в нём ограничено, во-вторых - на запуск твоих задач в пуле тоже требуются определённые накладные расходы.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
28.10.2019, 11:12  [ТС]
Так как все таки можно манипулиповать потоком createthread так, что бы к примеру в начале я создал 50 потоков, но после завершения переданной функции он не удалился сичтемой, а что бы я мог в какой либо из свободных из этих 50 потокоы опять активировать и отправить туда нужную функцию ?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
28.10.2019, 11:18
Цитата Сообщение от Optimus11 Посмотреть сообщение
Так как все таки можно манипулиповать потоком createthread так, что бы к примеру в начале я создал 50 потоков, но после завершения переданной функции он не удалился сичтемой, а что бы я мог в какой либо из свободных из этих 50 потокоы опять активировать и отправить туда нужную функцию ?
Никак.
Не завершай переданную функцию, а жди в ней события
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HANDLE evStop = ::CreateEvent(....);
HANDLE evDataReady = ::CreateEvent(....);
 
DWORD ThreadProc(void *arg)
{
    HANDLE events[] = {evStop, evDataReady, };
    for (;;)
    {
        const auto wait = ::WaitForMultipleObjects(std::size(events), events, FALSE, INFINITE);
        if (wait == WAIT_OBJECT_0)
            break;
 
        if (wait == WAIT_OBJECT_0 + 1)
            ProcessData();
    }
        retrurn 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.10.2019, 11:18

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

Как дождаться выполнения асинхронной функции?
Привет, Есть проэкт Node.js+angular+typescript. И у меня есть функция: window.speechSynthesis.speak(new...

Дождаться полного выполнения пула потоков
У меня пул потоков выполняет сортировку временных файлов: for (int i = 1; i &lt; tempFileCount; i++) { ...

Дождаться полного выполнения пула потоков
ExecutorService service = Executors.newFixedThreadPool(4); for (int i=0;i&lt;=fileCount;i++) { ...

Дождаться выполнения AJAX запроса и вернуть значение
Делаю расширение для хрома. Мне нужно из моего файла content отправить сообщение на background и получить ответ. Отправляю из content...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Просветление в 5 секунд
kumehtar 10.07.2026
Андрей Веретенников выдал фразу недавно: "Вам не обязательно кем-то себя считать"
Эксперимент с картинкой-обложкой на CodinGame
Adler 10.07.2026
Решил на днях провести эксперимент. У меня есть аккаунт на CodinGame, ТОП-3 по РФ среди 2200 участников (в разделе соревнования по программированию ИИ-ботов). Там есть обложка, куда можно влепить. . .
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru