简体   繁体   English

为什么我的表格会闪烁

[英]Why is my form blinking

I've implemented a simple multithreaded Server\\Client game as an assignment for my college. 我已经实现了一个简单的多线程Server \\ Client游戏作为我的大学的任务。

on the client side in addition to the main thread there are: 在客户端除主线程外还有:

1-thread which is responsible of drawing the play ground and the players on the form. 1线程,负责在表格上绘制比赛场地和球员。

2-thread to communicate with the server to send the directions and receive the location and other information. 2线程与服务器通信发送方向和接收位置等信息。

first I used the invoke technique but it didn't work because I was using the Graphics after it disposed. 首先我使用了invoke技术,但它没有用,因为我在处理后使用了Graphics。 see Draw on a form by a separate thread 请参阅单独的线程在表单上绘制

so In order to avoid that and regularize the drawing thread, I just raising the flag 'Invalidate' every specific time on the drawing thread and leave the actual handling of it to the main 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);
        }
    }

the problem here that the form is blinking in arbitrary fashion even though I'm using double buffering, and the blinking is reduced when I increase the sleeping time for the drawing thread, but I think 200ms is already too much. 这里的问题是,即使我正在使用双缓冲,表单也会以任意方式闪烁,当我增加绘图线程的休眠时间时,闪烁会减少,但我认为200ms已经太多了。 any advice? 任何建议?

[Edit] [编辑]

I realized that I'm setting the double buffering flag from the code and from the property editor which made the problem (this may be a fool idea) but I spent half an hour testing my code with one of the flags and with both of them, the problem raised when I set the double buffering flag from two places, my problem is solved but please now I need to know if this could be what solved it. 我意识到我正在从代码和属性编辑器中设置双缓冲标志,这会产生问题(这可能是一个愚蠢的想法)但我花了半个小时用一个标志和两个标志测试我的代码,当我从两个地方设置双缓冲标志时引发的问题,我的问题已经解决但现在我需要知道这是否可以解决它。

It must get worse and worse the longer it runs right? 它运行的时间越长,情况就越糟糕吗?

Everytime your program paints it launches draw, which has an infinite loop, which calls paint, which calls draw in another infinite loop. 每次你的程序绘制它时都会启动draw,它有一个无限循环,它调用paint,它调用另一个无限循环中的draw。 IT seems you have a circular reference here. 你似乎在这里有一个循环引用。 If I can assume Map.Draw is private void Draw() 如果我可以假设Map.Draw是私有的void Draw()

There is a far easier solution to this, draw everything to a bitmap then draw the bitpmap in the onPaint event. 有一个更简单的解决方案,将所有内容绘制到位图,然后在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;
     }
}

Note I did not test this for syntax accuracy. 注意我没有测试这个语法的准确性。

The memory of the system might be quite low for the operation executed. 对于执行的操作,系统的内存可能非常低。 read more about it. 阅读更多相关信息。 http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx http://msdn.microsoft.com/en-us/library/system.drawing.graphics.aspx

  1. Create an image which will be used to store last rendered scene. 创建将用于存储上次渲染场景的图像。
  2. Create new thread whith will draw to the image 创建新的线程将绘制到图像
  3. Create a timer whitch will refresh image 创建一个计时器whitch将刷新图像
  4. Copy image to form on timer tick 将图像复制到计时器刻度上

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM