C# 正在尝试绘制多线程矩形
我试图在一个表单上画3600点,使用一个线程速度非常慢,所以我决定使用4个线程 在我的代码中,我将3600个点分为4个线程,它们应该绘制它。但是由于某些原因,正在抛出ArgumentOutOfRangeException。 我试图调试我的代码,但找不到错误 代码如下: (忽略类3DPoint,它只是一个具有x,y,z值的点。当我绘制它们时,我只使用x,y值。) 绘制点的代码:C# 正在尝试绘制多线程矩形,c#,multithreading,winforms,C#,Multithreading,Winforms,我试图在一个表单上画3600点,使用一个线程速度非常慢,所以我决定使用4个线程 在我的代码中,我将3600个点分为4个线程,它们应该绘制它。但是由于某些原因,正在抛出ArgumentOutOfRangeException。 我试图调试我的代码,但找不到错误 代码如下: (忽略类3DPoint,它只是一个具有x,y,z值的点。当我绘制它们时,我只使用x,y值。) 绘制点的代码: public Graphics g; //g = this.CreateGraphics() in form1.
public Graphics g; //g = this.CreateGraphics() in form1.Load()
public void drawrectangle(_3DPoint)
float xCord = float.Parse(p.x.ToString());
float yCord = float.Parse(p.y.ToString());
Brush b = new SolidBrush(Color.White);
xCord = lsize * xCord + center.X;
yCord = lsize * yCord + 10 + center.Y;
g.FillRectangle(b, xCord, yCord, 2, 2);
}
public List<_3DPoint[]> multiThreadsdata = new List<_3DPoint[]>();
public void handlemultithread(_3DPoint[] P)
{
g.Clear(Color.Black);
for (int i = 0; i < multiThreads.Length; i++)
{
multiThreadsdata.Add(new _3DPoint[P.Length / multiThreads.Length]);
}
for (int i = 0; i < multiThreads.Length; i++)
{
for (int j = (P.Length / multiThreads.Length) * (i); j < (P.Length / multiThreads.Length) * (i + 1); j++)
{
multiThreadsdata[i][j - ((P.Length / multiThreads.Length) * i)] = new _3DPoint(P[j]);
}
}
for (int i = 0; i < multiThreads.Length; i++)
{
multiThreads[i] = new Thread(() => drawPoints(multiThreadsdata[i]));
multiThreads[i].Start();
}
}
delegate void SetCallBackPoint(_3DPoint location);
public void drawPoints(_3DPoint[] locations)
{
for (int i = 0; i < locations.Length; i++)
{
if (this.InvokeRequired)
{
SetCallBackPoint e = new SetCallBackPoint(drawrectangle);
this.Invoke(e, new object[] { locations[i] });
}
else
{
drawrectangle(locations[i]);
}
}
}
lsize、center只是我想要的对齐点的变量
所有多线程操作代码:
public Graphics g; //g = this.CreateGraphics() in form1.Load()
public void drawrectangle(_3DPoint)
float xCord = float.Parse(p.x.ToString());
float yCord = float.Parse(p.y.ToString());
Brush b = new SolidBrush(Color.White);
xCord = lsize * xCord + center.X;
yCord = lsize * yCord + 10 + center.Y;
g.FillRectangle(b, xCord, yCord, 2, 2);
}
public List<_3DPoint[]> multiThreadsdata = new List<_3DPoint[]>();
public void handlemultithread(_3DPoint[] P)
{
g.Clear(Color.Black);
for (int i = 0; i < multiThreads.Length; i++)
{
multiThreadsdata.Add(new _3DPoint[P.Length / multiThreads.Length]);
}
for (int i = 0; i < multiThreads.Length; i++)
{
for (int j = (P.Length / multiThreads.Length) * (i); j < (P.Length / multiThreads.Length) * (i + 1); j++)
{
multiThreadsdata[i][j - ((P.Length / multiThreads.Length) * i)] = new _3DPoint(P[j]);
}
}
for (int i = 0; i < multiThreads.Length; i++)
{
multiThreads[i] = new Thread(() => drawPoints(multiThreadsdata[i]));
multiThreads[i].Start();
}
}
delegate void SetCallBackPoint(_3DPoint location);
public void drawPoints(_3DPoint[] locations)
{
for (int i = 0; i < locations.Length; i++)
{
if (this.InvokeRequired)
{
SetCallBackPoint e = new SetCallBackPoint(drawrectangle);
this.Invoke(e, new object[] { locations[i] });
}
else
{
drawrectangle(locations[i]);
}
}
}
我不知道问题出在哪里,我猜多线程有一些问题,因为我只是一个多线程的初学者
非常感谢。在评论中应用建议时,完全可以在表单上快速绘制3600个矩形
如果这并不能给你足够的时间,你可以考虑在单个背景线程上创建图像,将它们存储在某种缓冲区中,直到它们需要在“代码>图形< <代码> >对象的“代码>油漆/<代码>事件”窗体上绘制。只有在你能预先知道下一帧需要画什么的情况下,这才是可行的
本例使用一个简单的后台工作程序来填充图像。代码中的注释解释了发生了什么public partial class Form1 : Form
{
static ConcurrentQueue<Image> buffer = new ConcurrentQueue<Image>();
static Random r = new Random();
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
// this is already a great performance win ...
DoubleBuffered = true;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Image img =null;
// get from buffer ..
if (!buffer.TryDequeue(out img))
{
// nothing available
// direct random
for (var x = 0; x < e.ClipRectangle.Width; x++)
{
for (var y = 0; y < e.ClipRectangle.Height; y++)
{
using (var pen = new Pen(new SolidBrush(Color.FromArgb(r.Next(255), r.Next(255), r.Next(255)))))
{
e.Graphics.DrawRectangle(pen, x, y, 1, 1);
}
}
}
}
else
{
// otherwise Draw the prepared image
e.Graphics.DrawImage(img,0,0);
Trace.WriteLine(buffer.Count);
img.Dispose();
}
}
private void button1_Click(object sender, EventArgs e)
{
// force a repaint of the Form
Invalidate();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// as long as the form is not disposed
while (!IsDisposed)
{
// we keep 60 images in memory
if (buffer.Count < 60)
{
// bitmap
var bmp = new Bitmap(this.Width, this.Height);
var img = Graphics.FromImage(bmp);
// draw
for (int i = 0; i < 3600; i++)
{
using (var pen = new Pen(new SolidBrush(Color.FromArgb(r.Next(255), r.Next(255), r.Next(255)))))
{
img.DrawRectangle(pen, r.Next(Width),r.Next(Height), r.Next(Width), r.Next(Height));
}
}
// store the drawing in the buffer
buffer.Enqueue(bmp);
}
else
{
// simple and naive way to give other threads a bit of room
Thread.Sleep(0);
}
}
}
}
公共部分类表单1:表单
{
静态ConcurrentQueue缓冲区=新ConcurrentQueue();
静态随机r=新随机();
公共表格1()
{
初始化组件();
backgroundWorker1.RunWorkerAsync();
//这已经是一个伟大的性能胜利。。。
双缓冲=真;
}
私有void Form1_Paint(对象发送器、PaintEventArgs e)
{
图像img=null;
//从缓冲区获取。。
如果(!buffer.TryDequeue(out img))
{
//没有可用的
//直接随机
对于(var x=0;x
请记住,当您有一个CPU繁忙的进程时,添加更多线程并不会神奇地使您的方法运行得更快。您甚至可能会让情况变得更糟:更多的线程在CPU上争夺时间。Winforms UI不是多线程的,您也不能同时从多个线程在同一个GDI+表面上绘制。多线程是一种既困难又昂贵的方法——在猜测方法时要非常小心,这是一种获得大量难以跟踪和修复的微妙错误的好方法。更不用说,由于您正在执行
Invoke
操作,因此您会在UI线程上马歇尔每一次回退,在保持实际工作负载100%单线程的同时浪费大量资源。总的来说,代码中存在很多性能问题-多线程不应该是您尝试的第一件事。“this.CreateGraphics”不好,请在内部使用事件绘制和e.Graphics,并激活DoubleBuffered=true。您将看到性能的提高。使用线程使某些东西“更快”会让您整天失望。@MattWilko我将回到单个线程,并尝试使用x。。。关于这方面的建议。我来看看是怎么回事。如果可以避免的话,也不要为每个点创建笔刷。这个解决方案非常有用,但我会将点的数量增加10-15,以使图形更详细。我想是否有一种方法可以将绘图部分分配给GPU,而不是让CPU来完成?注意:我无法预测下一张图片会是什么样子。谢谢。我刚刚检查了你的代码有多快,但还不够快。我可能不得不提到,我需要它画得足够快,如果用户按下一个按钮,它就会改变得足够快,这样看起来就流畅了。我正在屏幕上移动一个3d功能。包括左右向上向下以及在x轴、y轴和z轴上的旋转。有大约10-12个按钮用于移动。好吧,好吧,对于GDI缺乏任何支持的那种东西,System.Drawing.Successive中没有魔法。我会把你的答案标记为正确的,因为这是一个相当好的性能升级。非常感谢。