gpt4 book ai didi

c# - 通过单独的线程在表单上绘制

转载 作者:行者123 更新时间:2023-11-30 20:05:46 25 4
gpt4 key购买 nike

我正在尝试构建一个多线程游戏,其中我有一个单独的线程用于在不是主线程的窗体上绘画。这将我们带到了线程安全技术,我已经阅读了很多关于它的文章,但我不确定我是否理解正确。

我的问题是我有一个结构,其中每个数据对象都在表单上自行绘制,所以我不知道如何实现它。

这是我的工作单线程代码片段:

public partial class Form1 : Form
{
GameEngine Engine;
public Form1()
{
InitializeComponent();
Engine = new GameEngine();
}
protected override void OnPaint(PaintEventArgs e)
{
Engine.Draw(e.Graphics);
}

class GameEngine
{

Maze Map;
List<Player> Players;

public void Draw(Graphics graphics)
{
Map.Draw(graphics);
foreach (var p in Players)
{
p.Draw(graphics);
}
}

所以请任何人给我提示或好文章的链接,帮助我学习如何在另一个线程上分离绘图?

[编辑]

我设法实现了我打算做的事情这就是我的编码方式

    protected override void OnPaint(PaintEventArgs e)
{
formGraphics = e.Graphics;
DisplayThread = new Thread(new ThreadStart(Draw));
DisplayThread.Start();
}

private void Draw()
{
if (this.InvokeRequired)
{
this.Invoke(new DrawDelegate(this.Draw));
}
else
{
Engine.Draw(formGraphics);
}
}

但我得到一个 ArgumentException:参数无效

请指出该代码中的错误

最佳答案

我认为您需要绘制位图,然后在 OnPaint 方法中将该位图绘制到窗口。我稍后会演示。

正如 Hans 所指出的,在您设置的 OnPaint 方法中

formGraphics = e.Graphics;

但是在方法的末尾 e.Graphics 被释放,所以你不能再使用它了,如果你的代码必须

Engine.Draw(formGraphics);

你会得到一个异常(exception)。

所以基本上你需要有一个全局

Bitmap buffer = new Bitmap(this.Width, this.Height)

在您的异步线程中,您将调用您可以使用的位图的绘图

Graphics g=Graphics.FromBitmap(buffer);//

要获取图形对象,但请记住您必须

g.Dispose()

它或将它包裹在

using (Graphics g=Graphics.FromBitmap(buffer))
{
//do something here

}

我要试一试,看看能不能给你一个工作样本

编辑 这是您的工作示例。我开始了一个新表格并在上面扔了一个按钮。我将 mainform backgroundimagelayout 更改为 none。

我认为您需要使用 .net 4.0 或更高版本,如果不使用它,请告诉我我可以更改它以匹配您的版本...我认为。

//you need this line to use the tasks
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

public void Draw()
{
Bitmap buffer;
buffer = new Bitmap(this.Width, this.Height);
//start an async task
Task.Factory.StartNew( () =>
{
using (Graphics g =Graphics.FromImage(buffer))
{
g.DrawRectangle(Pens.Red, 0, 0, 200, 400);
//do your drawing routines here
}
//invoke an action against the main thread to draw the buffer to the background image of the main form.
this.Invoke( new Action(() =>
{
this.BackgroundImage = buffer;
}));
});

}

private void button1_Click(object sender, EventArgs e)
{
//clicking this button starts the async draw method
Draw();
}

}

关于c# - 通过单独的线程在表单上绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10714358/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com