Рисование полигонов с использованием многопоточности в Stack Overflow

Я рисую полигоны (Polygon (dc, points, 3)), используя событие WM_PAINT, используя C ++. У меня много полигонов, поэтому я пытаюсь реализовать многопоточность. Я бегу VS2013, поэтому я включил поток. Я создал функцию, которую хочу запустить в потоке:

void anyFunс2(HDC dc, int index)
{
POINT points[3];

for (unsigned i = index; i < model->vertexFaces.size(); i += fs)
{
// Here we convert our points to Clip and Windowed Coordinates
// and only then fetch the results
if (Algorithms::FetchPolygons(&model->finalizedVertices[0], model->vertexFaces[i], points))
{
Polygon(dc, points, 3);
}
}
}

Например, у меня есть три темы. Я разработал код так, чтобы каждый поток отображал каждый третий элемент. Например, первый поток отображает 0,3,6,9 полигонов, второй поток отображает 1,4,7,10, а последний поток — 2,5,8,11 полигонов.

Вот мое событие WM_PAINT:

case WM_PAINT:
{
// Get dc here
hdc = GetDC(hWnd);

// Create a backbuffer here
bdc = CreateCompatibleDC(hdc);

// Get the screen dimensions
RECT client;
GetClientRect(hWnd, &client);

// Create bitmap
HBITMAP backBuffer = CreateCompatibleBitmap(hdc, client.right - client.left, client.bottom - client.top);

// Release it, because we no longer need it
hdc = NULL;
ReleaseDC(hWnd, hdc);

// Select the back dc as a current one and specify the screen dimensions
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0, 25, 205));
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 55));

SelectObject(bdc, hPen);
SelectObject(bdc, hBrush);
SelectObject(bdc, backBuffer);

Rectangle(bdc, client.left, client.top, client.right, client.bottom);

// Call some threads to draw polygons on our BDC
for (unsigned i = 0; i < func_threads.size(); i++)
{
func_threads.at(i) = thread(anyFunс2, bdc, i);
}

// Wait until all threads finish their job
for (unsigned i = 0; i < func_threads.size(); i++)
{
if (func_threads[i].joinable()) func_threads[i].join();
}

// Swap buffers
hdc = BeginPaint(hWnd, &ps);
BitBlt(hdc, client.left, client.top, client.right, client.bottom, bdc, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);

// Delete all created objects from memory
DeleteObject(backBuffer);
DeleteObject(hBrush);
DeleteObject(hPen);
DeleteDC(bdc);
break;
}

Как видите, я запускаю эти темы в цикле. Затем у меня есть еще один цикл, где метод Join () расположен для каждого потока. Эти потоки рисуют полигоны на одном и том же HDC (я полагаю). После того, как основной поток завершил ожидание всех этих потоков, он копирует все из заднего буфера в основной. Однако проблема в том, что объект нарисован не полностью. Я имею в виду, что не все полигоны нарисованы. Ссылка на изображение прилагается Вот. Пожалуйста, помогите мне, почему это происходит так ?!

1

Решение

Короткий ответ: GDI просто не предназначен для поддержки рисования из нескольких потоков в одном DC одновременно.

Это оставляет вам несколько вариантов. Наиболее прямым было бы использовать PolyPolygon нарисовать все свои полигоны (или, по крайней мере, их большое количество) за один вызов. Это кажется особенно актуальным в вашем случае — судя по всему, вы рисуете много треугольников, так что, вероятно, много времени уходит на накладные расходы, чтобы вызвать Polygon функция, а не время для Polygon выполнить.

Другой возможностью было бы создать отдельный обратный буфер для каждого потока для рисования, а затем использовать BitBlit, чтобы объединить их вместе (например) с функцией OR, чтобы вы получили тот же общий эффект, что и исходный рисунок.

Третий (и, вероятно, лучший) способ поддержки рисования большого количества полигонов — это переключиться с использования GDI на использование чего-то вроде DirectX или OpenGL, разработанного с нуля для поддержки именно этого.

4

Другие решения

Вы можете использовать CreateDIBsection () для рисования фигур с несколькими потоками.
Просто пусть каждый поток рисует пиксели прямо в DIB. Затем, когда все потоки будут завершены, вы можете включить DIB на экран.

0

По вопросам рекламы [email protected]