Вопрос по multithreading, c# – Нарисуйте на форме отдельной нитью

2

Я пытаюсь создать многопоточную игру, в которой у меня есть отдельный поток для рисования на форме, который не является основным потоком. это приводит нас к поточно-ориентированной технике, о которой я прочитал много статей, но я не совсем уверен, что понял ее правильно.

у меня проблема в том, что у меня есть структура, в которой каждый объект данных рисует сам в форме, поэтому я не понял, как его реализовать.

это фрагмент моего рабочего однопоточного кода:

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: параметр недействителен

не могли бы вы указать на ошибку в этом коде

Итак, куда вы хотите вставить потоки в этот код? Tudor
@ Тудор, отвечая на ваш вопрос, пожалуйста, смотрите Редактировать абзац Alaa Arori
Какая строка бросаетArgumentException? Tudor
Вы используете e.Graphics после его утилизации. Вы не можете сделать это. Hans Passant

Ваш Ответ

1   ответ
7

вам нужно будет нарисовать растровое изображение, а затем в методе OnPaint нарисовать это растровое изображение в окне. Я продемонстрирую через минуту.

Как указал Ганс, в методе OnPaint вы устанавливаете

formGraphics = e.Graphics;

но в конце метода располагается e.Graphics, так что вы больше не сможете его использовать, если ваш код попал в

Engine.Draw(formGraphics);

Вы бы получили исключение.

Так что в основном вам нужно иметь глобальный

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

в вашей асинхронной ветке вы вызываете свой рисунок к этому растровому изображению, которое вы можете использовать

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

Чтобы получить графический объект, но помните, что вы должны

g.Dispose()

это или завернуть в

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

}

Я собираюсь поиграть с ним несколько минут и посмотреть, смогу ли я получить вам рабочий образец

EDIT  Вот ваш рабочий образец. Я запустил новую форму и бросил на нее кнопку. Я изменил фоновое изображение основной формы на 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();
    }

}

}

Error: User Rate Limit Exceeded Alaa Arori
Error: User Rate Limit Exceeded

Похожие вопросы