为什么我的表格会闪烁

时间:2012-06-01 11:05:56

标签: c# winforms multithreading drawing

我已经实现了一个简单的多线程Server \ Client游戏作为我学院的作业。

客户端的

除主线程外还有:

1-thread,负责在表格上绘制比赛场地和球员。

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

首先我使用了invoke技术,但它没有用,因为我在处理后使用了Graphics。见Draw on a form by a separate thread

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

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

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

[编辑]

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

3 个答案:

答案 0 :(得分:2)

它运行的时间越长越糟越好?

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

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

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

注意我没有对此语法准确性进行测试。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

  1. 创建一个用于存储最后渲染场景的图像。
  2. 创建新线程,将绘制到图像
  3. 创建一个计时器whitch将刷新图像
  4. 将图像复制到计时器刻度上的表格