Draw a shape in a separate thread

I am trying to create a multi-threaded game where I have a separate thread for drawing on a form that is not the main thread. this leads us to a thread-safe technique, which I read a lot of articles about, but I'm not sure I understood correctly.

my problem is that I have a structure in which each data object draws itself in shape, so I did not understand how to implement it.

this is a snippet of my working code with a mono stream:

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); } } 

}

so please can someone give me a hint or a link to a good article to help me learn how to separate a picture from another thread?

[change]

I managed to implement what I intended to do and this is how I encoded it

  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); } } 

but I got ArgumentException argument: parameter is not valid

could you point out an error in this code

+2
multithreading c # winforms
May 23 '12 at 6:07 a.m.
source share
1 answer

I think you will need to draw in the bitmap, then in the OnPaint method draw this bitmap in the window. I will demonstrate in a moment.

As Hans pointed out, in the OnPaint method you set

 formGraphics = e.Graphics; 

but at the end of the e.Graphics method is placed, so you can no longer use it if your code got to

 Engine.Draw(formGraphics); 

you will get an exception.

So basically you need to have global

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

in your asynchronous stream, you will reference your drawing to this bitmap, which you can use

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

To get a graphic, but remember that you must

 g.Dispose() 

or wrap it in

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

I'm going to play with him for a few minutes and see if I can get a working sample.

EDIT Here is your working sample. I started a new form and threw a button on it. I changed mainform backgroundimagelayout to none.

I think you need to use .net 4.0 or better, if not using this, let me know that I can change it to suit your version ... I think.

 //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(); } } 

}

+6
May 23 '12 at 11:15
source share



All Articles