0

我已经实现了一个简单的多线程服务器\客户端游戏作为我大学的作业。

在客户端除了主线程还有:

1-thread 负责绘制游戏场地和表格上的玩家。

2线程与服务器通信以发送方向并接收位置和其他信息。

首先我使用了调用技术,但它不起作用,因为我在处理它之后使用了 Graphics。请参阅通过单独的线程在表单上绘图

所以为了避免这种情况并规范绘图线程,我只是在绘图线程上的每个特定时间提升标志'无效'并将其实际处理留给主线程:

    public Form1()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        InitializeComponent();
    }

    private void Draw()
    {
        while (true)
        {
            Thread.Sleep(200);
            Invalidate();
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        if (map.hasGraph)
        {
            map.Draw(e.Graphics);
            if (this.Index != null)
                e.Graphics.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                e.Graphics.FillRectangle(OpponentBrush, OpponentRectangle);
        }
    }

这里的问题是,即使我使用双缓冲,表单也会以任意方式闪烁,并且当我增加绘图线程的睡眠时间时,闪烁会减少,但我认为 200 毫秒已经太多了。有什么建议吗?

[编辑]

我意识到我正在从产生问题的代码和属性编辑器中设置双缓冲标志(这可能是一个愚蠢的想法),但我花了半个小时用一个标志和两个标志来测试我的代码,当我从两个地方设置双缓冲标志时出现的问题,我的问题已解决,但现在我需要知道这是否可以解决它。

4

3 回答 3

2

运行时间越长,它一定会变得越来越糟,对吗?

每次你的程序绘制它都会启动draw,它有一个无限循环,它调用paint,它在另一个无限循环中调用draw。看来您在这里有一个循环引用。如果我可以假设 Map.Draw 是私有的 void Draw()

有一个更简单的解决方案,将所有内容绘制到位图,然后在 onPaint 事件中绘制位图。

Bitmap buffer=new Bitmap(this.Width, this.Height); //make sure to resize the bitmap during the Form.Onresize event
Form1()
{
    InitializeComponent();
    Timer timer=new Timer();
    timer.Interval= 100;
    timer.Tick+=......
    timer.Start()
}

//the Timer tick event
private void timer_tick(....
{
    if (map.hasGraph)
    {
         using (Graphics g = Graphics.FromImage(buffer))
        {
            //You might need to clear the Bitmap first, and apply a backfround color or image
            //change color to whatever you want, or don't use this line at all, I don't know
            g.Clear(Color.AliceBlue);

            if (this.Index != null)
                g.FillRectangle(Brush, Rectangle);
            if (OpponentIndex != null)
                g.FillRectangle(OpponentBrush, OpponentRectangle);
        }
     panel1.BackgroundImage=buffer;
     }
}

注意我没有测试这个语法的准确性。

于 2012-06-01T11:16:48.393 回答
0
  1. 创建将用于存储最后渲染场景的图像。
  2. 创建将绘制到图像的新线程
  3. 创建一个计时器会刷新图像
  4. 将图像复制到计时器刻度上
于 2012-06-01T11:57:11.643 回答
0

对于执行的操作,系统的内存可能非常低。阅读更多关于它的信息。 http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx

于 2012-06-01T11:14:32.660 回答