2012-06-01 68 views
0

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

上除了主线程客户端

有:

1线程负责画图玩的理由和形式对玩家的。

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

首先我使用的调用技术,但因为我用的是它的图形配置后,没有工作。看到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的已经太多了。 有什么建议吗?

[编辑]

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

+2

显示您如何使用双缓冲,有一个为没有证据它在片段中。 –

+0

这可能会发生,如果你把它抹掉,然后将你的缓冲图像绘制到它上面。而不是最后一个缓冲图像。 – Doomsknight

+0

我们可以假设这是winforms吗?什么是绘画,绘画盒,面板的控制? –

回答

2

它必须得到每况愈下的时间越长它运行吗?

每次你的程序描绘它启动画,其中有一个无限循环,它调用paint,这就要求再拉一个无限循环。看来你在这里有一个循环引用。如果我可以假设Map.Draw是私人无效的draw()

有一个更容易的解决了这个,一切都画成位图然后绘制bitpmap在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; 
    } 
} 

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

+0

如果你愿意,我可以更好地解释这一点。但它应该消除很多闪烁问题,我将频率设置为每秒10帧,将刻度值更改为任何您想要的值,以每秒5帧的速度更改该值。更改timer.interval =(以毫秒为单位) –

+0

I可能没有很清楚地描述这个想法,我相信我没有循环引用,因为draw方法是一个独立线程的开始方法,所以没有人调用它,但是负责任的线程。任何看到的版本。 –

0
  1. 创建一个图像,将用于存储最后呈现的场景。
  2. 创建新的线程蒙山将绘制到图像
  3. 创建一个定时器whitch将刷新图像
  4. 复制图像,从而在计时器滴答