功能导致屏幕闪烁冻结

时间:2011-07-24 01:03:54

标签: c# winforms timer pixel overloading

我有一个不那么复杂的功能,但出于某种原因,每次我调用它时,它会冻结屏幕四分之一秒。此功能位于计时器上,每秒都会部署一次,因此对用户来说非常烦人。

该功能基本上获得了屏幕的屏幕截图,通过比较10个像素检查它正在寻找的屏幕,如果是屏幕则返回true,否则返回false:

ClassName.CheckScreen(CaptureScreen(),ClassName.Pxarr1); //Capture screen isn't the problem. It gave me no freezes in an endless loop.

该课程:

class ClassName
{
    public static Pixel[] Pxarr1 = new[]
    {
        new Pixel(Color.FromArgb(255, 204, 204, 170), new Point(15, 145)),
        new Pixel(Color.FromArgb(255, 221, 204, 187), new Point(20, 460)),
        new Pixel(Color.FromArgb(255, 221, 204, 187), new Point(20, 545)),
        new Pixel(Color.FromArgb(255, 204, 187, 170), new Point(15, 150)),
        new Pixel(Color.FromArgb(255, 221, 204, 187), new Point(22, 190)),
        new Pixel(Color.FromArgb(255, 204, 204, 187), new Point(25, 540)),
        new Pixel(Color.FromArgb(255, 204, 187, 153), new Point(22, 61)),
        new Pixel(Color.FromArgb(255, 221, 204, 170), new Point(23, 563)),
        new Pixel(Color.FromArgb(255, 204, 187, 153), new Point(23, 47)),
        new Pixel(Color.FromArgb(255, 204, 204, 187), new Point(23, 463)),

    };

    public static Pixel[] Pxarr2 = new[]
    {
        new Pixel(Color.FromArgb(255, 221, 255, 119), new Point(80, 120)),
        new Pixel(Color.FromArgb(255, 51, 119, 221), new Point(180, 525)),
        new Pixel(Color.FromArgb(255, 204, 170, 85), new Point(630, 455)),
        new Pixel(Color.FromArgb(255, 85, 153, 17), new Point(707, 177)),
        new Pixel(Color.FromArgb(255, 255, 153, 34), new Point(520, 440)),
        new Pixel(Color.FromArgb(255, 255, 238, 51), new Point(150, 325)),
        new Pixel(Color.FromArgb(255, 0, 85, 255), new Point(455, 70)),
        new Pixel(Color.FromArgb(255, 255, 221, 51), new Point(685, 285)),
        new Pixel(Color.FromArgb(255, 17, 17, 17), new Point(547, 369)),
        new Pixel(Color.FromArgb(255, 170, 170, 136), new Point(500, 545)),

    };

    public static Pixel[] Pxarr3 = new[]
    {
        new Pixel(Color.FromArgb(255, 238, 238, 238), new Point(353, 223)),
        new Pixel(Color.FromArgb(255, 28, 33, 49), new Point(428, 198)),
        new Pixel(Color.FromArgb(255, 85, 85, 85), new Point(462, 314)),
        new Pixel(Color.FromArgb(255, 221, 221, 238), new Point(450, 450)),
        new Pixel(Color.FromArgb(255, 102, 102, 102), new Point(384, 349)),
        new Pixel(Color.FromArgb(255, 204, 204, 204), new Point(406, 248)),
        new Pixel(Color.FromArgb(255, 221, 221, 221), new Point(464, 453)),
        new Pixel(Color.FromArgb(255, 255, 204, 17), new Point(413, 198)),
        new Pixel(Color.FromArgb(255, 204, 204, 204), new Point(343, 447)),
        new Pixel(Color.FromArgb(255, 255, 255, 255), new Point(403, 457)),

    };

    public static Pixel[] Pxarr4 = new[]
    {
        new Pixel(Color.FromArgb(255, 204, 170, 136), new Point(120, 227)),
        new Pixel(Color.FromArgb(255, 221, 187, 153), new Point(502, 170)),
        new Pixel(Color.FromArgb(255, 119, 85, 34), new Point(692, 243)),
        new Pixel(Color.FromArgb(255, 238, 221, 187), new Point(211, 169)),
        new Pixel(Color.FromArgb(255, 187, 170, 136), new Point(272, 238)),
        new Pixel(Color.FromArgb(255, 170, 153, 119), new Point(696, 64)),
        new Pixel(Color.FromArgb(255, 136, 85, 17), new Point(306, 242)),
        new Pixel(Color.FromArgb(255, 187, 170, 119), new Point(115, 236)),
        new Pixel(Color.FromArgb(255, 204, 187, 153), new Point(310, 183)),
        new Pixel(Color.FromArgb(255, 153, 102, 34), new Point(647, 245)),

    };

    public static Pixel[] Pxarr5 = new[]
    {
        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(376, 150)),
        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(376, 350)),

        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(506, 150)),
        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(506, 350)),

        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(246, 150)),
        new Pixel(Color.FromArgb(255, 255, 238, 221), new Point(246, 350))
    };

    public static bool CheckScreen(Bitmap img, Pixel[] samples)
    {
        int verifiedpixels = 0;
        for (int i = 0; i < samples.Length; i++)
        {
            Color c = img.GetPixel(samples[i].Location.X, samples[i].Location.Y);
            if (c == samples[i].Color)
                    verifiedpixels++;
        }
        return verifiedpixels >= (samples.Length * 0.6);
    }

}

注意:使用CaptureScreen()的语句的100循环速度是文件中的图像的两倍。 (4秒vs 2秒)

但是,我仍然不明白为什么这个函数会冻结任何冻结,即使是文件中的图像也是如此。

2 个答案:

答案 0 :(得分:2)

由于您使用的是计时器,因此它不应该冻结UI,除非您使用的System.Windows.Forms.Timer将在UI线程上执行其回调。而是使用System.Timers.TimerSystem.Threading.TimerSystem.Timers.Timer的示例:

private System.Timers.Timer _checkPixelsTimer = new System.Timers.Timer();

public Form1()
{
    InitializeComponents();

    _checkPixelsTimer.Intervla = 1000;//one second
    _checkPixelsTimer.AutoReset = true;
    _checkPixelsTimer.Elapced += OnCheckPixelsTimerElapced;
    _checkPixelsTimer.Start();
}

private void OnCheckPixelsTimerElapced(object sender, System.Timer.ElapcedEventArgs e)
{
    if (ClassName.CheckScreen(CaptureScreen(),ClassName.Pxarr1))
    {
        MethodInvoker method = new MethodInvoker(() => { /*code that relays on the UI thread */ });
        if (this.InvokeRequired)
        {
            this.Invoke(method); 
        }
        else
        {
            method();
        }
    }
}

修改:更新代码以预览如何在UI线程中调用函数。

答案 1 :(得分:1)

GetPixel()和SetPixel()非常慢。

使用其他方法,例如LockBits()/ UnlockBits()技术。见Fast work with Bitmaps in C#