Форум программистов, компьютерный форум CyberForum.ru

Потоки. Основа. - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.67
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 18:53     Потоки. Основа. #1
Помогите разобраться с потоками WinAPI.
Нужны только азы.
Для начала создание, уничтожение, передача параметров
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "stdafx.h"
#include <WinBase.h>
 
 
DWORD WINAPI func(PVOID param)
{
 
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    CreateTread(NULL, 0, func, param, 0);
    
    return 0;
}
1.) у CreateTread тип возвращаемого значения - HANDLE. Это что-то типо адреса потока? Где его запоминать?
2.) PVOID и LPVOID. Нашёл, что LPVOID отличается от PVOID тем, что он "far". Как мне помнится, это слово влияет на возможноть расположение в области памяти, отличной от главного потока.
3.) главный поток - это инт тмейн? или нужно начать программу по-другому?
4.) то, что на писано, не компилируется. Выдаётся много ошибок типа:
C++
1
2
3
4
5
6
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(300): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "wMinute"
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(300): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(300): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(301): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "wSecond"
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(301): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>c:\program files (x86)\microsoft sdks\windows\v7.0a\include\winbase.h(301): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
5.) Передача параметров. Скажем, я хочу передать в функцию два иттератора. Непонятен сам процесс передачи параметров...что мне следует делать? Загонять оба иттератора в структуру?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.03.2012, 18:53     Потоки. Основа.
Посмотрите здесь:

Потоки с++ C++
потоки.. C++
потоки C++
Потоки C++
Потоки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 19:09     Потоки. Основа. #2
1) Хендл потока, своеобразный идентификатор. Нужен, чтобы потом у этому потоку можно было обращаться
2) far это макрос который ничему не равен. В Windows нет длинных и коротких указателей. Только один на всех.
3) int main() - примерно так, первый код, запускаемый в первичном потоке, исключая глобальные переменные, которые равны значениям функций и прочую лабуду. Если приложение оконное, то вместо int main() WinMain
4) надо подключать windows.h, а не winbase.h
5) загонять в структуру

Добавлено через 41 секунду
С итераторами вообще аккуратней. Они потокозависимы.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 19:30  [ТС]     Потоки. Основа. #3
Так, уже лучше)
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
#include "stdafx.h"
#include <Windows.h>
#include <vector>
#include <iostream>
using namespace std;
 
template <typename T>
struct para
{
    T begin,end;
    para (T b, T e)
    {
        begin = b;
        end = e;
    }
};
 
DWORD WINAPI func(PVOID param)
{
 
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    para<vector<int>::iterator> p(b.begin(), b.end());
 
    CreateThread(NULL, 0, func, p, 0);
    
    return 0;
}
1.) Как же всё-таки передать мою пару иттераторов в func?
2.) Где можно хранить хендл потока? Если я создам
C++
1
HANDLE potok[10]
там можно?
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 19:42     Потоки. Основа. #4
1)
не понятно, что такое b, но не суть.
C++
1
2
para<vector<int>::iterator> p(b.begin(), b.end());
CreateThread(NULL, 0, func, (LPVOID)&p, 0);
C++
1
2
3
4
DWORD WINAPI func(PVOID param)
{
 para<vector<int>::iterator> *p = (para<vector<int>::iterator>*) param;
}
2) Хранить можно где угодно. Главное, что бы был доступ.
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
11.03.2012, 19:43     Потоки. Основа. #5
Цитата Сообщение от IcyWind Посмотреть сообщение
1.) Как же всё-таки передать мою пару иттераторов в func?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef para<vector<int>::iterator> iterator_pair;
 
DWORD WINAPI func(PVOID param)
{
    iterator_pair p = *static_cast<iterator_pair*>(param);
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    iterator_pair p(b.begin(), b.end());
 
    CreateThread(NULL, 0, func, &p, 0);
        
    return 0;
}
но берегитесь. в передаче итераторов - целый букет подводных камней. шаг в сторону и бб.
Цитата Сообщение от IcyWind Посмотреть сообщение
2.) Где можно хранить хендл потока? Если я создам
C++
1
HANDLE potok[10]
там можно?
зачем вам 10 хэндлов? хватит одного
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 20:10  [ТС]     Потоки. Основа. #6
Цитата Сообщение от retmas Посмотреть сообщение
зачем вам 10 хэндлов? хватит одного
Ну я к примеру)

Печально, что приходится самому программисту заботиться о том, чтобы разделить param на то, что ему надо...

1.)
C++
1
iterator_pair p = *static_cast<iterator_pair*>(param);
тут p - это ТИП
я заменил строчку на
C++
1
iterator_pair* p = static_cast< iterator_pair * > (param);
теперь p - это указатель на ТИП. Правильно?

2.) Либо поток не работает, либо ещё что-то...вообщем, компилируется, но не выводит элементы вектора
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
38
39
40
41
42
43
44
45
46
#include "stdafx.h"
#include <Windows.h>
#include <vector>
#include <iostream>
using namespace std;
 
template <typename T>
struct para
{
    T begin,end;
    para (T b, T e)
    {
        begin = b;
        end = e;
    }
};
 
typedef para<vector<int>::iterator> iterator_pair;
 
 
 
 
DWORD WINAPI func(PVOID param)
{
    iterator_pair* p = static_cast< iterator_pair * > (param);
    while( p->begin != p->end )
    {
        cout<< *p->begin;
        ++p->begin;
    }
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    vector<int> b;
    b.push_back(5);
    b.push_back(4);
    b.push_back(3);
    b.push_back(2);
 
    //iterator_pair p(b.begin() , b.end());
    CreateThread(NULL, 0, func, &iterator_pair(b.begin(), b.end()), 0, NULL);
    
    return 0;
}
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 20:18     Потоки. Основа. #7
Передаете временный объект и не ждете завершения потока. У вас программа сразу завершается после вызова потока.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 20:20  [ТС]     Потоки. Основа. #8
А можете, пожалуйста, написать строку для ожидания завершения потока?
скажем
C++
1
2
HANDLE potok = CreateThread(NULL, 0, func, &iterator_pair(b.begin(), b.end()), 0, NULL);
While(potok.??? )
А временный объект я передаю намеренно. Разве есть ошибка?
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
11.03.2012, 20:21     Потоки. Основа. #9
в мэйне надо дожидаться завершения потока.
и раскомментируйте свою строчку в мэйне и передавайте указатель на р, а не на временный объект
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
11.03.2012, 20:22     Потоки. Основа. #10
А почему вы пользуетесь какой-то CreateThread вместо того чтобы использовать _beginthread?
Вот вам в тему заодно пример из книги Петзолда на мультипотоковость
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
 
#define REP 1000000 // 100 000
 
#define STATUS_READY 0
#define STATUS_WORKING 1
#define STATUS_DONE 2
 
#define WM_CALC_DONE (WM_USER+0)
#define WM_CALC_ABORTED (WM_USER+1)
 
typedef struct
{
    HWND hwnd;
    BOOL bContinue;
} 
PARAMS, *PPARAMS;
 
LRESULT APIENTRY WndProc(HWND, UINT, WPARAM, LPARAM);
 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow)
{
    static char szAppName[]="BigJob1";
    MSG msg;
    HWND hwnd;
 
    WNDCLASSEX wndclass;
 
    ZeroMemory(&wndclass, sizeof(wndclass));
 
    wndclass.cbSize=sizeof(wndclass);
    wndclass.style=CS_HREDRAW|CS_VREDRAW;
    wndclass.lpfnWndProc=WndProc;
    wndclass.hInstance=hInstance;
    wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground=(HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszClassName=szAppName;
    wndclass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wndclass);
 
    hwnd=CreateWindow(szAppName, "Multithreading Demo", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
 
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
 
void Thread(PVOID pvoid)
{
    double A=1.0;
    INT i;
    LONG lTime;
    PPARAMS pparams;
 
    pparams=(PPARAMS) pvoid;
    
    lTime=GetCurrentTime();
    for(i=0;i<REP && pparams->bContinue;i++)
        A=tan(atan(exp(log(sqrt(A*A)))))+1.0;
    if(i==REP)
    {
        lTime=GetCurrentTime()-lTime;
        SendMessage(pparams->hwnd, WM_CALC_DONE, 0, lTime);
    }
    else
        SendMessage(pparams->hwnd, WM_CALC_ABORTED, 0, lTime);
    _endthread();
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    static char *szMessage[]={"Ready (left mous button begins)",
        "Working (right mouse button aborts)",
        "%d repetitions in %ld msec"};
    static INT iStatus;
    static LONG lTime;
    static PARAMS params;
    char szBuffer[64];
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
 
    switch(iMsg)
    {
    case WM_LBUTTONDOWN:
        if(iStatus==STATUS_WORKING)
        {
            MessageBeep(0);
            return 0;
        }
        iStatus=STATUS_WORKING;
 
        params.hwnd=hwnd;
        params.bContinue=TRUE;
 
        _beginthread(Thread, 0, &params);
        InvalidateRect(hwnd, NULL, TRUE);
        return 0;
 
    case WM_RBUTTONDOWN:
        params.bContinue=FALSE;
        return 0;
 
    case WM_CALC_DONE:
        lTime=lParam;
        iStatus=STATUS_DONE;
        InvalidateRect(hwnd, NULL, TRUE);
        return 0;
 
    case WM_CALC_ABORTED:
        iStatus=STATUS_READY;
        InvalidateRect(hwnd, NULL, TRUE);
        return 0;
 
    case WM_PAINT:
        hdc=BeginPaint(hwnd, &ps);
 
        GetClientRect(hwnd, &rect);
 
        wsprintf(szBuffer, szMessage[iStatus], REP, lTime);
 
        DrawText(hdc, szBuffer, -1, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 20:26     Потоки. Основа. #11
А можете, пожалуйста, написать строку для ожидания завершения потока?
WaitForSingleObject(potok, INFINITE);

А временный объект я передаю намеренно. Разве есть ошибка?
Да, после вызова функции переданный временный объект уничтожится.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 20:31  [ТС]     Потоки. Основа. #12
Хм...для лучшего понимания:
временный объект уничтожится прямо после создания потока. Поэтому в саму функцию он не попадёт.
вроде выходит так...

Добавлено через 22 секунды
Я думал, что он перестанет существовать после выхода из функции
retmas
Жарю без масла
803 / 685 / 143
Регистрация: 13.01.2012
Сообщений: 1,580
11.03.2012, 20:32     Потоки. Основа. #13
ф-я получает копию указателя. но на что он указывает? подумайте
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 20:34     Потоки. Основа. #14
IcyWind, в функцию он попадет. Но будет валиден только на первой итерации цикла поточной функции.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 23:22  [ТС]     Потоки. Основа. #15
А указывает он на только что переставший существовать объект?

Добавлено через 59 минут
Теперь вопрос в синхронизации потоков...
если на пальцах, то есть два потока.
в обоих как-то двигаюсь по итераторам (it1 и it2)
в какой-то момент времени поток останавливается и ждёт, пока остановится другой поток (собираюсь сделать это с помощью событий)
после этого нужно сделать swap(it1, it2).
Есть версия с return it1/2 из функции потока...и последующем создании новых потоков...но, мне кажется, это будет ОЧЕНЬ ресурсоёмко.
Подскажете?

Добавлено через 1 час 45 минут
ау...
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 23:24     Потоки. Основа. #16
Я вообще изначально не понимаю всю идею. В общих чертах, что должна программа делать и зачем нужны потоки.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 23:29  [ТС]     Потоки. Основа. #17
Ну вообще не хотел говорить сам алгоритм)
хочу, чтобы он был моим
изначально задача стоит - сортировка в два потока для 100% загрузки обоих ядер.
причём использовать нужно стандартную сортировку (ну, скажем из stl sort).
Мне нужно 2 потока, по 1 на каждое ядро.
алгоритм следующий:
сначала, как для быстрой сортировки, разбить массив на 2 части
одна часть больше числа А. Вторая - меньше.
ну и sort для каждой из частей по-отдельности
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 23:32     Потоки. Основа. #18
Т.е. в сумме 2 потока? Разбиваем массив, запускаем 2 потока и все?
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
11.03.2012, 23:34  [ТС]     Потоки. Основа. #19
Ну, у меня получится 2потока для разбиения массива, а потом ещё 2 потока для сортировки каждой частей.
но в единицу времени должно работать не более 2-х потоков, да

Добавлено через 1 минуту
Есть вариант сделать разбиение в мейне...но в 2 потока гораздо эффективней...
вот и нужно научиться свапать элемент, найденный одним потоком с элементом, найденным другим
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.03.2012, 23:36     Потоки. Основа.
Еще ссылки по теме:

Потоки C++
В равнобедренном треугольнике известна основа с и угол при ней C++
Потоки C++

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

Или воспользуйтесь поиском по форуму:
gooseim
Эксперт C++
500 / 404 / 35
Регистрация: 23.09.2010
Сообщений: 1,139
11.03.2012, 23:36     Потоки. Основа. #20
Только я не очень понимаю как можно сортировать весь массив по частям.

Добавлено через 28 секунд
В итоге то что делать с отсортированными частями.
Yandex
Объявления
11.03.2012, 23:36     Потоки. Основа.
Ответ Создать тему
Опции темы

Текущее время: 23:06. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru