Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SetWaitableTimer(), как задать период срабатывания таймера 
V
    Опции темы
wallstreet
Дата 9.4.2012, 22:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Цитата

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


Ну так еще бы, проект сырой очень, да и вообще)
На самом деле постоянно что-то меняю что-то пробую, поэтому и переменных куча ненужных.
Вобщем впреть постараюсь сразу удалять. Хорошее замечание!

Цитата

Ну как минимум count_column во втором форе нужно переинициализировать в 0. Вообще, все векторные прибомбасы стоило отложить на самый конец, имхо.
Как максимум нужно разобраться с итераторами (что выводит TextOut?).


Да, точно. Теперь матрица заполняется правильно, но неправильными числами. (сейчас я изменил заполнение на рендомное)
А с чем конкретно в итераторах? Я неправильно с ними работаю? Пробовал в консоле данную структуру создания и вывода, все работало как часы. 

1/ ОК. Убрал секцию cs, только теперь смущает, что первый поток, который по идее должен был заниматься выделением памяти под данные, не занимается ничем. Ну да ладно..

2/ сsX - защищает модификацию и чтение вектора

3/ 
Цитата

cx и cy - есть характеристики битмапа hMemSharedBitmap. Менять их нужно только в тот момент, в который изменяется значение hMemSharedBitmap, а не в любой произвольный момент. Переменные hMemSharedBitmap, cx, cy защищаются критической секцией csShared.

Если я инициализирую значения сх и су в потоке3, в секции csShared то растр не отрисовывается в WM_PAINT.
Цитата

::scrlh - есть характеристика вектора (в прошлом - буфера), менять значение этой переменной стоит тогда, когда мы изменяем размер вектора (или буфера). Вектор и ::scrlh защищаются критической секцией cs.

Значение переменной ::scrlh  изменяет локальная переменная scrlh диалога1 на значение выбранное скроллбаром в обработке нажатия кнопки "ОК". Собственно оную нажав мы и изменяем исходные параметры размерности моего вектора и растра. Т.е. мы открыли диалог1, выбрали размерность матрицы, нажали "ОК" и матрица должна сразу же поменять размер и перерисоваться на главном окне. Именно поэтому, как мне казалось, правильнее было прилепить запуск потоков к обрабоке нажатия кнопки ОК, что я и делал, но вопрос с Таймером для меня был открыт. Вобщем, если с потоками все понятно, то как изменить значение переменной ::scrlh  в потоке2, для меня загадка?!?! В принципе можно создать еще одну переменную, локальную для потока2 и брать значение глобальной ::scrlh, но есть ли в этом смысл?

4/ Честно признаться не помню уже какую цель преследовал, но явно над чем-то эксперементировал методом тыка)

5/ Таймер будет скоро. Если не сложно, подскажите как я могу его запускать из диалога1 и где его устанавливать, т.к. он запускает потоки, а они у меня запускаются при создании окна и второй раз их запускать таймером будет неправильно. 

6/ Ну основную логику описал в п. 3. Просто думал так, что запуск потоков с созданием и отрисовкой матрицы необходимо делать после того как пользователь определится с ее размером, а самым лучшим для этого подтверждением является нажатие на кнопку "ОК". Сейчас то, с вашей помощью, я уже понял как можно по другому (страшно сказать правильно smile ).

7/ Удалил ненужные, а вот hMemBitmap очень даже нужная. Это наш растр, который мы создаем в потоке2, а в потке3 инициализируем им hMemSharedBitmap. Однако в глобале ей делать нечего и это факт)

8/ Ну моя цель работы над данным проектом это учеба. С сбытиями разобрался, теперь представилась возможность попрактиковаться с семафорами. Почему бы и нет smile


Ссылка на проект тут -> обновленный вариант

Это сообщение отредактировал(а) wallstreet - 10.4.2012, 10:09
PM MAIL   Вверх
wallstreet
Дата 11.4.2012, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Вот я прописал таймер.
Он у меня создается в момент создания окна. Создается без задержек и сразу же запускает потоки, но потоки не отрисовывают раст, т.к. семафорХ не запущен. Этот семафор освободит диалог1 после того как пользователь определится с размерностью матрицы, которую хочет видеть на экране и нажмет кнопку "ОК". 
Предположим пользователь сидит и смотрит на пустое окно и размерность массива не выбирает, даже диалог1 не открывает. Так вот мне интересно, в этот момент мой таймер что делает, создает раз в секунду поток, который ожидает освобождения семафораХ? 
Так вот вопросы эти появляются только потому, что после того как я определю размерность матрицы в диалоге1 программа отрисует один раз мой растр и все. Да еще и непонятно почему заполняет только матрицу 10х10 правильно, а при заполнении 5х5, к примеру, то будет она выглядеть вот так:
user posted image
хотя должен был начинаться второй ряд с 5 6 7 8 9, ну и тд.
И что самое главное картинка не перерисовывается с новой матрицей, хотя вроде и цикл есть в потоках, но не хочет. Почему?(



Ссылка на проект тут=>проект
Заранее благодарю за ответы!

Это сообщение отредактировал(а) wallstreet - 11.4.2012, 17:45
PM MAIL   Вверх
GremlinProg
Дата 12.4.2012, 07:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  11.4.2012,  19:38 Найти цитируемый пост)
Вот я прописал таймер.Он у меня создается в момент создания окна. Создается без задержек и сразу же запускает потоки, но потоки не отрисовывают раст, т.к. семафорХ не запущен. Этот семафор освободит диалог1 после того как пользователь определится с размерностью матрицы, которую хочет видеть на экране и нажмет кнопку "ОК". 

таймер должен заменить семафорХ, а не дополнить,
просто удали семафорХ,

диалог теперь не должен запускать поток, т.к. он запускается таймером,
но возникает еще один конфликт, подобный hSharedBitmap: переменная scrlh в таком случае тоже должна быть защищена из диалога и в потоках

теперь по коду:
1. у тебя опять путаница в ролях потоков: зачем первый поток очищает массив, когда он должен задавать его размер?
2. ладно, очищает, но почему без синхронизации?
3. "ЗАПОЛНЕНИЕ ВЕКТОРА" ну сам же пишешь: "ЗАПОЛНЕНИЕ", т.е. заполнение его данными, а почему я вижу в цикле push_back? второй поток не должен вызывать ни каких операций, связанных с изменением размеров вектора, этим должен заниматься первый поток,

соответственно, раз cx и cy напрямую зависят от scrlh, второй поток тоже не должен трогать эти переменные,
оставь и эту работу первому потоку

Цитата(wallstreet @  11.4.2012,  19:38 Найти цитируемый пост)
Предположим пользователь сидит и смотрит на пустое окно и размерность массива не выбирает, даже диалог1 не открывает. Так вот мне интересно, в этот момент мой таймер что делает, создает раз в секунду поток, который ожидает освобождения семафораХ? 

не создает, а пробуждает, или запускает,
на счет семафораХ уже сказал, на данный момент его должен заменить таймер

в принципе, задача так и стоит: по таймеру пускать всю цепочку событий, пользователю, конечно это может не так интересно наблюдать,

я бы мог предложить более интересный вариант:
заполнять массив не тупо значением j++, а добавить сюда элемент уникальности, например factor * j++,
тогда factor будет один раз инициализироваться перед заполнением массива, например так:
Код

factor = int( 10.0 * float( rand() ) / RAND_MAX );

тогда всякий раз, после запуска цепочки, картинка будет меняться,
пользователю будет не так скучно,

ну, или можно вообще отвязать изменение factor от потоков, а менять его значение в диалоге, вручную
Цитата(wallstreet @  11.4.2012,  19:38 Найти цитируемый пост)
Так вот вопросы эти появляются только потому, что после того как я определю размерность матрицы в диалоге1 программа отрисует один раз мой растр и все.

ну, это потому, что у тебя тут стоит TRUE:
Цитата

list[0] = hTimer;
list[1] = hSemaphoreX;
WaitForMultipleObjects(2,  list, TRUE, INFINITE);        // Ждем освобождения hSemaphoreX

а должно быть как минимум FALSE, ну а как оптимум: hSemaphoreX тут быть не должно,
хотя, если бы задача стояла: пускать первый поток либо по таймеру, либо по активности пользователя, то можно было бы и оставить,
это интересная практика, да и пользователю хорошо: изменения сразу вступают в силу, после закрытия диалога
Цитата(wallstreet @  11.4.2012,  19:38 Найти цитируемый пост)
почему заполняет только матрицу 10х10 правильно, а при заполнении 5х5, к примеру, то будет она выглядеть вот так:

а что не нравится?
тут все верно:
Код

_itot(*itV, str, vv.size());

это означает, что для 10x10 значения массива будут выведены в 10-чной системе счисления, для 5x5 - в 5-чной и т.д.
если надо все выводить в 10-чной, передавай в последний параметр 10, а не vv.size()


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
feodorv
Дата 12.4.2012, 18:03 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



Цитата(GremlinProg @  12.4.2012,  08:34 Найти цитируемый пост)
таймер должен заменить семафорХ, а не дополнить,
просто удали семафорХ,

Здесь я не совсем согласен smile 
Изначально Event0 нужен был только для того, чтобы пробудить Thread1 не дожидаясь срабатывания таймера (то есть для корректного завершения программы).
В сущности, для этого же нужен SemaphoreX, ни больше ни меньше. То есть он нужен (если им правильно пользоваться):
Код

        WaitForMultipleObjects(2,  list, TRUE, INFINITE);        // Ждем освобождения hSemaphoreX

Конечно, так не годится. Ожидается и таймер и семафор одновременно. Зачем? Почему не так:
Код

WaitForMultipleObjects(2,  list, FALSE, INFINITE); 

Ээээ... Увидел
Цитата(GremlinProg @  12.4.2012,  08:34 Найти цитируемый пост)
а должно быть как минимум FALSE, ну а как оптимум: hSemaphoreX тут быть не должно,
хотя, если бы задача стояла: пускать первый поток либо по таймеру, либо по активности пользователя, то можно было бы и оставить,
это интересная практика, да и пользователю хорошо: изменения сразу вступают в силу, после закрытия диалога
 smile 


Цитата(GremlinProg @  12.4.2012,  08:34 Найти цитируемый пост)
соответственно, раз cx и cy напрямую зависят от scrlh, второй поток тоже не должен трогать эти переменные,
оставь и эту работу первому потоку

Опять же, не совсем согласен  smile 
cx и cy используются в отрисовке битмапа:
Код

BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY);               // Отрисовываем раст

Менять отдельно cx, cy и hMemSharedBitmap не стоит!!! Иначе говоря cx и cy нужно менять в Thread3 в момент
Код

hMemSharedBitmap = hMemBitmap;                                   // присваиваем значение hMemSharedBitmap нарисованного растра



То есть:
Код

unsigned int scrlhReal; // текущий размер 
unsigned int scrlhNew; // новый размер, который станет текущим в Thread1

unsigned _stdcall Thread1(void *param)
{
    while(!done)
    {
                ...
        WaitForMultipleObjects(2,  list, FALSE, INFINITE); 
        if(done) break;
        EnterCriticalSection(&csX);

        // Резайзим вектор
                scrlhReal = scrlhNew; // Сейчас вектор и его размер не соответствуют друг другу!!!
                ...resizeVector( scrlhReal );... // В этот момент вектор и его размер соответствуют друг другу
                // Но поскольку мы защищены критической секций, то всё в порядке))))

        LeaveCriticalSection(&csX);
        ReleaseSemaphore( hSemaphoreY, 1, NULL);
    }

    return 0;
}

unsigned _stdcall Thread2(void *param)
{
    while(!done)
    {
        WaitForSingleObject( hSemaphoreY, INFINITE);
        if(done) break;

        EnterCriticalSection(&csX);
        for( int column=0; column<scrlhReal; ++column)
        {
            for( int row=0; row<scrlhReal; ++row)
            {  
                           // Заполняем вектор
                           ...
            }
        }    
        LeaveCriticalSection(&csX);

        ReleaseSemaphore(hSemaphoreZ, 1, NULL);
    }
    return 0;
}

unsigned _stdcall Thread3(void *param)
{
    HDC hScreenDC, hMemDC;
    HGDIOBJ hMemBitmap;
    int dx, dy;

    while(!done)
    {
        WaitForSingleObject( hSemaphoreZ, INFINITE);
        if(done) break;

        hScreenDC = ::GetDC(HWND_DESKTOP);                         
        hMemDC = CreateCompatibleDC(hScreenDC);                    
        hMemBitmap = CreateCompatibleBitmap(hScreenDC, cx, cy);
        ::ReleaseDC(HWND_DESKTOP, hScreenDC);
        hMemBitmap = ::SelectObject( hMemDC, hMemBitmap);
        
        EnterCriticalSection(&csX);
        // Рисуем растр
        for( int count_row = 0, itVv=vv.begin(); itVv!=vv.end(); itVv++, count_row++)
        {
            for( int count_column = 0, itV=itVv->begin(); itV!=itVv->end(); itV++, count_column++)
            {
                _itot(*itV, str, 10);
                TextOut(hMemDC, count_column*30, count_row*30, str, _tcslen(str));
            }
        }

    dx = vv.size() * 30;
    dy = vv.size() * 30;
    LeaveCriticalSection(&csX);

    hMemBitmap = ::SelectObject( hMemDC, hMemBitmap); 
    ::DeleteDC(hMemDC); 

    EnterCriticalSection(&csShared);
        if( hMemSharedBitmap != NULL ) DeleteObject( hMemSharedBitmap );
        hMemSharedBitmap = hMemBitmap; 
    cx = dx;
    cy = dy;
    LeaveCriticalSection(&csShared);

        InvalidateRect((HWND)param, FALSE, TRUE);
    }

    return 0;
}



Тут же встают проблемы инициализации и очистки  smile 

Код

        hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
        SetWaitableTimer(hTimer, &lTime, 1000, NULL, NULL, FALSE);
        hThread1 = (HANDLE)_beginthreadex(NULL, 0, Thread1, hWnd, 0, NULL);
        hThread2 = (HANDLE)_beginthreadex(NULL, 0, Thread2, hWnd, 0, NULL);
        hThread3 = (HANDLE)_beginthreadex(NULL, 0, Thread3, hWnd, 0, NULL);

Цитата(wallstreet @  11.4.2012,  18:38 Найти цитируемый пост)
Он у меня создается в момент создания окна. Создается без задержек и сразу же запускает потоки, но потоки не отрисовывают раст, т.к. семафорХ не запущен. Этот семафор освободит диалог1 после того как пользователь определится с размерностью матрицы, которую хочет видеть на экране и нажмет кнопку "ОК". 

Если хочется всё стартовать через Dialog1, то можно сделать так:
Код

BOOL inited = FALSE; // глобальная переменная

BOOL launchDialog( HWND owner )
{
  if( DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), owner, Dialog1) == IDOK )
  {
    if( !inited )
    {
    hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
    SetWaitableTimer(hTimer, &lTime, 1000, NULL, NULL, FALSE);
    hThread1 = (HANDLE)_beginthreadex(NULL, 0, Thread1, hWnd, 0, NULL);
    hThread2 = (HANDLE)_beginthreadex(NULL, 0, Thread2, hWnd, 0, NULL);
    hThread3 = (HANDLE)_beginthreadex(NULL, 0, Thread3, hWnd, 0, NULL);
        inited = TRUE;
    }
    return TRUE;
  }
  return FALSE;
}


Соответственно в Dialog1:
Код

...
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case IDOK:
            scrlhNew = scrlh;
            j = 0;
        
        case IDCANCEL:
            return EndDialog(hDlg, LOWORD(wParam)); // <-----------!!!!
        }
        return TRUE;
...


Соответственно в WndProc убрать код инициализации hTimer, ThreadXXX и 
Код

...
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_FILE_SETTINGS:
            launchDialog( hWnd );
            break;
...


Можно launchDialog вызвать и в момент окончания инициализации главного окна (принудить пользователя к действиям), но это особая история...


Код

        case IDM_EXIT:
            done = TRUE;
            // чистим вектор
            vv.clear();
            HANDLE list[3];
            list[0] = hThread1;
            list[1] = hThread2;
            list[2] = hThread3;
            WaitForMultipleObjects(3, list, TRUE, 10000); // Ждем завершения всех потоков
                        ...

Во-первых, vv.clear() стоит делать только после завершения всех потоков. Во-вторых, потоки нужно предварительно пробудить. В-третьих
Код

            DeleteDC(hMemDC);

это лишнее, а вот hMemSharedBitmap освободить нужно!!! В четвёртых, надо освободить таймер. В пятых, перед ожидаем потоков, стоит проверить, что они вообще были запущены. То же к таймеру и семафорам.


Цитата(wallstreet @  9.4.2012,  23:09 Найти цитируемый пост)
Ну так еще бы, проект сырой очень, да и вообще)

Да я не в притензии, я для дела сугубо)))


Цитата(GremlinProg @  12.4.2012,  08:34 Найти цитируемый пост)
это означает, что для 10x10 значения массива будут выведены в 10-чной системе счисления, для 5x5 - в 5-чной и т.д.
если надо все выводить в 10-чной, передавай в последний параметр 10, а не vv.size()

 smile 

Это сообщение отредактировал(а) feodorv - 12.4.2012, 18:18


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GremlinProg
Дата 13.4.2012, 07:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(feodorv @  12.4.2012,  20:03 Найти цитируемый пост)
Изначально Event0 нужен был только для того, чтобы пробудить Thread1 не дожидаясь срабатывания таймера (то есть для корректного завершения программы).В сущности, для этого же нужен SemaphoreX, ни больше ни меньше. То есть он нужен (если им правильно пользоваться):

Event0 - это семафорХ?
если так, то изначально этот семафор пускал первый поток,
о завершении потоков мы как-то уже договорились, что пока на нем заморачиваться не будем,

потом, для завершения всех потоков лучше сделать одно событие hAbort, которое и заменит флаг done
Цитата(feodorv @  12.4.2012,  20:03 Найти цитируемый пост)

cx и cy используются в отрисовке битмапа:
Код

BitBlt(hdc, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY);               // Отрисовываем раст

Менять отдельно cx, cy и hMemSharedBitmap не стоит!!!

если не опираться на cx и cy в 3-м потоке, при создании растра, то да, так будет безопасно для основного потока,
хотя он может получить эту же информацию из растра, через GetObject,

на счет безопасности в основном потоке я бы как раз пока особо не переживал,
я сейчас говорю об инициализации растра в 3-м потоке,

теоретически, раз от размера вектора зависит размер растра,
и размер вектора выставляется в критической секции x,
то разумно было бы и размер растра выставлять/получать в этом критическом участе кода,
тогда нет разницы, в каком потоке это будет сделано


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 13.4.2012, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Всем спасибо за помощь.
кое что подправил, завтра думаю добью если время будет.


Ссылка на проект =>проект
PM MAIL   Вверх
feodorv
Дата 13.4.2012, 21:36 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 9
Всего: 45



GremlinProg
Цитата(GremlinProg @  13.4.2012,  08:46 Найти цитируемый пост)
на счет безопасности в основном потоке я бы как раз пока особо не переживал,

Конечно, при отрисовке битмапа неверные cx и cy не скажутся на безопасности выполнения основного потока, но дело в принципе:
Код

unsigned _stdcall Thread1(void *param)
{
    while(!done)
    {
        HANDLE list[2];
        list[0] = hTimer;
        list[1] = hSemaphoreX;
        WaitForMultipleObjects(2, list, FALSE, INFINITE);        // Ждем освобождения hTimer или семафора
        if(done)
            break;
        EnterCriticalSection(&csX);                              // защита модификации и чтения вектора
        if(vv.size())
        {
            vv.resize(::scrlh);                                  // вот тут я не знаю правильно я это делаю или нет!!!!!
            vv.erase(vv.begin(), vv.end());                      // при уменьшении размера вектора отрисовка растра подтормаживает!!!!        
        }
        vv.reserve(::scrlh);                                     // задаем размер вектора если он нулевой

        ::cx = ::scrlh * 30;                                     // сразу же задаем размер переменных для битмапа
        ::cy = ::scrlh * 30;
        LeaveCriticalSection(&csX);
        ReleaseSemaphore(hSemaphoreY, 1, NULL);                  // Освобождаем hSemaphoreY для третьего потока
    }

    return 0;
}

Между Thread1 и Thread3 может случится WM_PAINT. При этом hMemSharedBitmap ещё старая, а значения cx и cy уже новые, не когерентные с hMemSharedBitmap...


Цитата(GremlinProg @  13.4.2012,  08:46 Найти цитируемый пост)
хотя он может получить эту же информацию из растра, через GetObject,

Вот это было бы лучше всего (чтобы не было путаницы), а от cx и cy можно будет отказаться вообще...


Цитата(GremlinProg @  13.4.2012,  08:46 Найти цитируемый пост)
теоретически, раз от размера вектора зависит размер растра,
и размер вектора выставляется в критической секции x,
то разумно было бы и размер растра выставлять/получать в этом критическом участе кода,
тогда нет разницы, в каком потоке это будет сделано 

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


wallstreet
Код

            vv.erase(vv.begin(), vv.end());                      // при уменьшении размера вектора отрисовка растра подтормаживает!!!!    

В смысле???


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GremlinProg
Дата 14.4.2012, 16:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(feodorv @  13.4.2012,  23:36 Найти цитируемый пост)
Между Thread1 и Thread3 может случится WM_PAINT

равно как и между Thread3 и WM_PAINT может случиться Thread1 и Thread2 smile
Цитата(feodorv @  13.4.2012,  23:36 Найти цитируемый пост)
vv.reserve(::scrlh);                                     // задаем размер вектора если он нулевой

reserve не задает размер вектора, здесь нужен resize
Цитата(feodorv @  13.4.2012,  23:36 Найти цитируемый пост)
Вот это было бы лучше всего (чтобы не было путаницы), а от cx и cy можно будет отказаться вообще...

 smile 
либо отказаться, либо завести еще пару, ибо под одним синхронизатором кто-нибудь обязательно будет в пролете: либо растр, либо WM_PAINT
Цитата(feodorv @  13.4.2012,  23:36 Найти цитируемый пост)
Прошу прощения, но эта мысль никак не желает достигнуть нужных отделов моего слабеющего мозга)))

судя по коду, она все же нашла, что искала  smile 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 17.4.2012, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Цитата

Вот это было бы лучше всего (чтобы не было путаницы), а от cx и cy можно будет отказаться вообще...

Ну, полностью отказаться я не знаю как, т.к. при создании растра hMemBitmap, в третьем потоке, мы задаем его размеры.
Код

hMemBitmap = CreateCompatibleBitmap(hScreenDC, cx, cy); 

В этот момент еще нет хендла растра из которого можем вытащить высоту и ширину. 
Т.о. я оставил инициализацию cx и cy в первом потоке исключительно для создания первого растра hMemBitmap. В то время как для отрисовки в WM_PAINT я ширину и высоту вытаскиваю из уже готового растра hMemSharedBitmap, которому до этого присваиваю hMemBitmap.
Если вы покажете способ избавиться от сх и су полностью, буду признателен.

Код

vv.resize(::scrlh);                                      // вот тут я не знаю правильно я это делаю или нет!!!!!
vv.erase(vv.begin(), vv.end());                          // при уменьшении размера вектора отрисовка растра подтормаживает!!!    

Цитата

В смысле???

Видимо я неполноценно выразил свою мысль, но если вы попробуете размер матрицы установить, предположим, в 10х10 с помощью скроллбара, а затем второй раз, уже рисующийся растр изменить на размер 5х5 с помощью все того же скроллбара, то заметите как он где-то на секунду приостановит отрисовку и потом уже нарисует правильный размер матрицы, а при увеличении размера, такой задержки не последует. Так вот меня интересовали причины по которым отрисовка подтормаживается при уменьшении размера растра. Собственно на выше приведенный участок кода я и стал грешить, хотя может зря, может причина в другом?


ссылка на проект:скачать проект
PM MAIL   Вверх
GremlinProg
Дата 18.4.2012, 06:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  17.4.2012,  18:53 Найти цитируемый пост)
Ну, полностью отказаться я не знаю как, т.к. при создании растра hMemBitmap, в третьем потоке, мы задаем его размеры.

Код

BITMAP Bm;
::GetObject( hSharedBitmap, sizeof( Bm ), &Bm );
Bm.bmWidth; // это cx
Bm.bmHeight; // это cy

Цитата(wallstreet @  17.4.2012,  18:53 Найти цитируемый пост)
vv.erase(vv.begin(), vv.end());

это равнозначно такому коду:
Код

vv.clear();

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

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


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 18.4.2012, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GremlinProg @ 18.4.2012,  08:40)
Цитата(wallstreet @  17.4.2012,  18:53 Найти цитируемый пост)
Ну, полностью отказаться я не знаю как, т.к. при создании растра hMemBitmap, в третьем потоке, мы задаем его размеры.

Код

BITMAP Bm;
::GetObject( hSharedBitmap, sizeof( Bm ), &Bm );
Bm.bmWidth; // это cx
Bm.bmHeight; // это cy


упс, недопонял  smile 
я этот код привел для WM_PAINT'а, т.е. не для 3-го, а для основного потока


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 18.4.2012, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Код

BITMAP Bm;
::GetObject( hSharedBitmap, sizeof( Bm ), &Bm );
Bm.bmWidth; // это cx
Bm.bmHeight; // это cy

да да да, именно так я и вытаскиваю высоту и ширину из hSharedBitmap в WM_PAINT, но не использовать сx и cy в третьем потоке не знаю как. Хотя по большому счету если не запустится поток2, то не запустится и поток3, а второй запускается только после того как зпускается поток1 в котором инициализируются сx и су. Так что между потоками нестыковок в работе не должно быть, а в WndProc при отрисовке берется высота и ширина из битмапа, так что думаю все ок тут с синхронизацией.
Цитата

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

Я понимаю так. Поток1 ресайзит вектор. Предположим, что он уже заполнен значениями 1, 2, 3, 4, 5. 
Так вот если я изменяю его размер вот так:
Код

vv.resize(8);

то получу в результате: 1, 2, 3, 4, 5, NULL, NULL, NULL и если я в дальнейшем не удалю значения оставив только размерность, то используя push_back() во втором потоке, значения вставятся непонятно как для меня. Т.е. если убрать удаление элементов вектора из потока1, то WM_PAINT отрисовывает черный квадрат заданой размерности, без чисел.
Изначально думал резервировать  память под вектор, если его размер 0, в потоке1 функцией reserve(), а в потоке2 заполнять исходя из его capacity() простым циклом. Если же вектор.size() > 0 тогда изменять его размер функцией resize(), но как проблему решить с очисткой от значений я не знал поэтому все на выходе получалось через стерни к звездам.

Добавлено через 14 минут и 11 секунд
вообще думал сделать изменение размера вектора и его заполнение как-то так:
Поток1
Код

if(!vv.size())                                           // если в векторе нет ни одного элемента, то
        {
            vv.reserve(::scrlh);                                 // устанавливаем вместимость вектора
        }
        else                                                     // если размер вектора больше 0
        {
            vv.resize(::scrlh);                                  // изменяем размер на актуальный
        }

Поток2
Код

// ЗАПОЛНЕНИЕ ВЕКТОРА
        if(!vv.size())                                           // если элементов нет (может произойти если мы изменили вместимость, 
                                                                 // но не заполнили) то
        {
            for(int column=0; column<vv.capacity(); ++column)    // заполняем матрицу случайными значениями, при этом сотрируем до 
                                                                 // максимально возможного размера вектора до того как ему потребуется 
                                                                 // выделить больше места column<vv.capacity()
            {                                                    
                for(int row=0; row<vv.capacity(); ++row)
                {  
                    ::j = rand()%100;
                    v.push_back(j++);
                }

                vv.push_back(v);
                v.clear();
            }
        }
        else
        {
            vv.assign(vv.begin(), vv.end());                     // Здесь мы перезаписываем наш вектор в этот же вектор, но с заменой значений
            for(int column=0; column<vv.size(); ++column)        // Тут испльзуем уже реальный размер вектора а не зарезервированый column<vv.size()
            {                                                    
                for(int row=0; row<vv.size(); ++row)
                {  
                    ::j = rand()%100;
                    v.push_back(j++);
                }

                vv.push_back(v);
                v.clear();
            }
        }

Но этот код не работает, матрица отрисовывается один раз и вылазит ошибка Debug Assertion Failed!
Expression: vector iterators incompatible
PM MAIL   Вверх
GremlinProg
Дата 18.4.2012, 12:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @ 18.4.2012,  14:30)

Цитата

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

Я понимаю так. Поток1 ресайзит вектор. Предположим, что он уже заполнен значениями 1, 2, 3, 4, 5. 
Так вот если я изменяю его размер вот так:
Код

vv.resize(8);

то получу в результате: 1, 2, 3, 4, 5, NULL, NULL, NULL и если я в дальнейшем не удалю значения оставив только размерность, то используя push_back() во втором потоке, значения вставятся непонятно как для меня. Т.е. если убрать удаление элементов вектора из потока1, то WM_PAINT отрисовывает черный квадрат заданой размерности, без чисел.
Изначально думал резервировать  память под вектор, если его размер 0, в потоке1 функцией reserve(), а в потоке2 заполнять исходя из его capacity() простым циклом. Если же вектор.size() > 0 тогда изменять его размер функцией resize(), но как проблему решить с очисткой от значений я не знал поэтому все на выходе получалось через стерни к звездам.

ну смотри, в первом потоке задаешь размер массива:
Код

vv.resize( new_size );
for( auto It = vv.begin() ; It != vv.end() ; ( It++ )->resize( new_size ) );

а во втором его заполняешь:
Код

for( auto It = vv.begin() ; It != vv.end() ; ++It ){
  for( auto Jt = It->begin() ; Jt != It->end() ; ++Jt ){
    *Jt = j++;
  }
}

если проблем с синхронизацией нет, значит ошибок тут тоже не будет, и не важно, какой размер был на предыдущей итерации,
черный квадрат у тебя точно не из-за того, что сохраняются старые значения в массиве


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
wallstreet
Дата 18.4.2012, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Цитата(GremlinProg @  18.4.2012,  12:51 Найти цитируемый пост)
for( auto It = vv.begin() ; It != vv.end() ; ( It++ )->resize( new_size ) );

эээ.. стесняюсь спросить auto это что?
насколько я понимаю it это итератор, но чем он отличается от std::vector<std::vector<int>>::iterator it?

Это сообщение отредактировал(а) wallstreet - 18.4.2012, 13:53
PM MAIL   Вверх
GremlinProg
Дата 18.4.2012, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(wallstreet @  18.4.2012,  15:52 Найти цитируемый пост)
но чем он отличается от std::vector<std::vector<int>>::iterator it

ни чем не отличается


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0720 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.