-
У вас DIB-секция - грубо говоря просто массив байт в памяти. Каким же образом GDI обязана "блокировать" доступ к ней? И зачем ей это?
Это вопрос не функций GDI, а синхронизации потоков.
Вы что, не имеете в своей многопоточной системе событий/сигналов типа "отрисовка кадра началась", "отрисовка кадра закончилась", "пора начать рисовать новый кадр"? Молотите как попало на максимуме процессора? Это как бы нехорошо.
-
>пора начать рисовать новый кадр Суть потоков в том, что в совокупности они настолько быстрые, что после вызова BitBlt они начинают рисовать в буфере который еще выводится. Т.е. система не успевает дорисовать до конца буфер, а потоки уже успевают в нем нарисовать новое. Флага в системе что отрисовка окончена нет. В одном потоке нет проблем.
-
Вообще вроде логично что надо дождаться пока кадр выведется, и тока потом продолжать рисование на этом кадре. Дак может сделаете свой?
... IsDrawing:=True; BitBlt(...); IsDrawing:=False; ...
Как бы логически аналог Lock/Unlock из TCanvas.
-
Вы странный человек. Это потоки. У меня рисует только один поток с ID=0. Остальные ждут пока он отрисует. Именно такой флаг и стоит. Только когда делается вызов BitBlt, поток ID=0 сразу после вызова функции выходит и возвращается в цикл где ждут остальные потоки, чтобы продолжить отрисовку, но сама BitBlt еще не успевает дорисовать!!! Сама функция еще не выполнена!!! Может она драйверу дает отрисовывать, может еще кому. Факт в том, что она не успевает дорисовать, а потоки уже рисуют в буфере. 20 потоков (в моем случае) это очень быстро!!!! BitBlt просто не потокобезопасна. Она жизнеспособна только в одном потоке. У меня и Synchronize стоит и флаги. Результат один и тот же.
Еще раз привожу код:
//Это процедура вывода на экран procedure TTestForm.UpdateThreads; var dp: TDrawParams;
begin if (not gThreadsUpdating) then begin gThreadsUpdating := true;
if bZBuffer then sBmp.DrawZBuffer;
//Информация и контролы sBmp.DrawSmallText(Rgn.X + 10, Rgn.Y + 10, Ansistring('Рисует ID: ' + HexToStr(Word(gFirstID)) + 'h'), 1, crWhite, 255, 64); dp.Angle := gAngle; if bInfo then TestForm.DrawCenterInfo(dp); RepaintControls; DrawProgress(gProgress, false); UpdateWindow; // <-Здесь находитя BitBlt
if b3D then sBmp.ClearZBuffer;
//Очищаем фон ClearBack;
//Счетчик обновлений Inc(gNumBufferUpdates);
gThreadsUpdating := false; end; end;
//Это цикл отрисовки procedure QThread.Execute; var cP: TFloatPoint; Params: TDrawParams;
label StopDraw;
begin //Параметры по умолчанию Params := FillParams;
//Центр вращения cP.fX := cX; cP.fY := cY;
//Порядковый номер потока NumberID := GetFreeID(ThreadID);
//Заполняем параметры Params.cX := cX; Params.cY := cY; Params.ThreadID := NumberID; Params.Angle := gAngle;
//Отсечение всего региона if bClip then Params.R := lmR else Params.R := Rgn;
//Цикл отрисовки while (gDrawCounter <= gNumDrawCycles) do begin //Превышение индекса объектов //учитывается в программе отрисовки //Рисуем ... gDrawProc(Params);
//Обновляет буфер самый шустрый поток if (ThreadID = gFirstID) then begin //Обновляем буфер Synchronize(TestForm.UpdateThreads); //<-- Synchronize не обязательно, но может моргать! //TestForm.UpdateThreads; //Прогресс gProgress := Round(gDrawCounter / (gNumDrawCycles - 1) * 100); //Кол-во циклов отрисовки Inc(gDrawCounter); //Следующий угол gAngle := RorAngle(gAngle, gAngleInc); //Сброс кол-ва отрисованных объектов gObjectIndex := 0; end;//if (gNumEntered)
//Устанавливаем флаг завершения отрисовки FPaints[NumberID] := True;
//Остальные потоки ждут здесь //пока первый поток не отрисует буфер //или все потоки не соберутся здесь while (not PaintsFinished) do begin //Проверка на превышение циклов отрисовки if (gDrawCounter >= gNumDrawCycles) then goto StopDraw; end;
//Проверка на ESC if gESC then goto StopDraw; end;//while
StopDraw:
//Устанавливаем флаг завершения отрисовки FPaints[NumberID] := True;
//Ждем здесь пока остальные потоки не закончат отрисовку while (not PaintsFinished) do begin end; end;
-
Короче добавил CriticalSection в UpdateThreads - скорость снизилась, но глюки исчезли. Значит Игорь Шевченко © (09.02.17 21:39) [4] был прав.
|