Функция заставляет экран мигать - PullRequest
0 голосов
/ 24 июля 2011

У меня есть функция, которая не так сложна, но по какой-то причине каждый раз, когда я ее вызываю, она замораживает экран примерно на четверть секунды. Эта функция включена по таймеру и разворачивается каждую секунду, поэтому она может раздражать пользователя.

Функция в основном получает снимок экрана экрана, проверяет, ищет ли экран, сравнивая 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);
    }

}

Примечание: цикл 100 для оператора был в два раза медленнее с CaptureScreen (), чем с изображением из файла. (4 секунды против 2 секунд)

Но, тем не менее, я не понимаю, почему эта функция вызывает зависание даже с изображением из файла.

Ответы [ 2 ]

2 голосов
/ 24 июля 2011

Поскольку вы используете таймер, он не должен замораживать пользовательский интерфейс, если вы не используете System.Windows.Forms.Timer , который выполнит свой обратный вызов в потоке пользовательского интерфейса. Вместо этого используйте System.Timers.Timer или System.Threading.Timer . Пример для System.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();
        }
    }
}

Редактировать: обновить код, чтобы просмотреть, как вызывать функцию в потоке пользовательского интерфейса.

1 голос
/ 24 июля 2011

GetPixel () и SetPixel () общеизвестно медленны.

Используйте альтернативный метод, такой как метод LockBits () / UnlockBits (). См. Быстрая работа с растровыми изображениями в C #

.
...