Rot*_*tem 5 c# graphics multithreading gdi+ winforms
我当然知道我不能Graphics从不同的线程绘制到同一个对象,但是我不能绘制到不同线程中的不同 Graphics对象也是真的吗?
考虑以下控制台程序:
class Program
{
static ThreadDrawer[] drawers;
static void Main(string[] args)
{
int numThreads = 8;
drawers = new ThreadDrawer[numThreads];
for (int i = 0; i < numThreads; i++)
{
drawers[i] = new ThreadDrawer();
drawers[i].Start();
}
for (int i = 0; i < numThreads; i++)
{
drawers[i].Wait();
}
Console.WriteLine("Complete.");
Console.ReadKey();
}
class ThreadDrawer
{
private Thread thread;
private AutoResetEvent resetEvent;
public ThreadDrawer()
{
thread = new Thread(DrawRandomCircles);
resetEvent = new AutoResetEvent(false);
}
public void Start()
{
thread.Start();
}
public void Wait()
{
resetEvent.WaitOne();
}
public void DrawRandomCircles()
{
Random r = new Random(Environment.TickCount);
using (Bitmap b = new Bitmap(1000, 1000))
using (Graphics g = Graphics.FromImage(b))
{
for (int i = 0; i < 100000; i++)
{
g.DrawEllipse(Pens.Red, new Rectangle(r.Next(1000), r.Next(1000), 200, 200));
}
}
resetEvent.Set();
}
}
}
Run Code Online (Sandbox Code Playgroud)
该程序Bitmap在每个线程中创建一个,并继续使用一个Graphics对象在其上绘制随机椭圆,该对象也是从Bitmap.
由于需要.net2使用Threads 和AutoResetEvents 而不是 TPL来实现多线程构建。
程序执行时不会抛出异常,但它是串行执行的。使用n线程n会使执行时间成倍增加,使用任务管理器可以清楚地看到只使用了一个内核。
需要注意的是,这些都与任何 UI 元素无关。
这里发生了什么?Graphics对象是否锁定在静态对象上?
这是我用来查看这些线程发生了什么的并发分析器的屏幕截图:

是的,您可以看到大量红色(阻塞)和绿色斑点(执行)。线程轮流进入在内部 GpGraphics::RenderDrawPath() 函数中获取的临界区。较大的绿色斑点是程序实际绘制线条的地方(我用 DrawRectangle 替换了 DrawEllipse 并去掉了 Random 调用)。
有一些并发性,例如,您可以看到 RenderDrawPath() 调用与呈现抗锯齿线的代码重叠,整体 CPU 负载约为 35%。但没有多少。
当然,您对此无能为力。您可以通过在自己的程序中重叠逻辑来决定使用 GDI+ 调用绘制什么内容。这通常会发生,测试太综合了。
| 归档时间: |
|
| 查看次数: |
1772 次 |
| 最近记录: |