C# c-按下按钮后形成“滞后”

C# c-按下按钮后形成“滞后”,c#,C#,我对我制作的一个游戏做了一个扩展,当你按下“搜索像素”时,它会自动按下一个按钮,但每次我按下按钮,无论成功与否,应用程序的内存都会增加大约30兆字节。从4.5 MB开始,然后单击按钮,它将上升到33.3 MB这是代码 { public Form1() { InitializeComponent(); } private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x

我对我制作的一个游戏做了一个扩展,当你按下“搜索像素”时,它会自动按下一个按钮,但每次我按下按钮,无论成功与否,应用程序的内存都会增加大约30兆字节。从4.5 MB开始,然后单击按钮,它将上升到33.3 MB这是代码


    {

        public Form1()
        {
            InitializeComponent();
        }

        private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
        private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;

        [DllImport("user32.dll")]
        private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, uint dwExtraInf);

        [DllImport("user32.dll")]
        private static extern bool SetCursorPos(int x, int y);

        private void OnButtonSearchPixelClick(object sender, EventArgs e)
        {
            // 01. get hex value from input field
            string inputHexColorCode = textBox1.Text;
            SearchPixel(inputHexColorCode);
        }

        private bool SearchPixel(string hexcode)
        {

            // Take an image from the screen
            // Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); // Create an empty bitmap with the size of the current screen 

            Bitmap bitmap = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height); // Create an empty bitmap with the size of all connected screen 

            Graphics graphics = Graphics.FromImage(bitmap as System.Drawing.Image); // Create a new graphics objects that can capture the screen

            graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size); // Screenshot moment → screen content to graphics object

            Color desiredPixelColor = ColorTranslator.FromHtml(hexcode);

            // Go one to the right and then check from top to bottom every pixel (next round -> go one to right and go down again)
            for (int x = 0; x < SystemInformation.VirtualScreen.Width; x++)
            {
                for (int y = 0; y < SystemInformation.VirtualScreen.Height; y++)
                {
                    // Get the current pixels color
                    Color currentPixelColor = bitmap.GetPixel(1550, 412);

                    // Finally compare the pixels hex color and the desired hex color (if they match, we found a pixel)
                    if (desiredPixelColor == currentPixelColor)
                    {
                        DoubleClickAtPosition(1387, 414);

                        return true;
                    }

                }
            }

            return false;
        }

        private void DoubleClickAtPosition(int posX, int posY)
        {
            SetCursorPos(posX, posY);

            Click();
            Thread.Sleep(250);
            Click();
        }

        private new void Click()
        {
            mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        }
    }
}
这段代码来自我观看的视频。如果你需要我做任何事情,如张贴视频或张贴任何其他代码,请让我知道,我真的需要帮助。 我还想说,我对c语言的编码还很陌生。

解释 Windows窗体使用单线程单元模型。这意味着Windows窗体中的一切,从渲染到处理Windows消息(如鼠标和键盘事件),都发生在一个线程中

您可能已经注意到,在所有WinForms应用程序中,您都可以在Program.cs中看到[STAThreadAttribute]。“STA”代表“单线公寓”

因为WinForms在单线程单元中运行,所以在WinForms STA线程中运行的任何密集型代码都会阻止WinForms呈现表单并处理其鼠标和键盘事件,因为它一次只能做一件事

解决方案 这里的解决方案是在WinForms STA线程的单独线程中运行强化SearchPixel函数

有很多方法可以实现这一点,例如后台工作人员或硬线程。然而,最简单和最可接受的方法是使用自动推迟到线程池的任务

这很简单,只需按如下方式更改代码:

private void OnButtonSearchPixelClick(object sender, EventArgs e)
{
    // 01. get hex value from input field
    string inputHexColorCode = textBox1.Text;
    Task.Run(() => {
        SearchPixel(inputHexColorCode);
    });
}
警告 由于您的代码将在WinForms的STA线程以外的线程中运行,因此不进行调用就无法与WinForms正在使用的任何对象进行交互

例如:

Task.Run(() => {
    label1.Text = "Test";
});
将导致InvalidOperationException,因为您试图访问WinForms希望仅在其单线程单元中访问的对象

您必须告诉STA线程调用一个操作,这将导致代码在STA线程中运行。像这样:

Task.Run(() => {
    //Code in here will run in a thread pool

    this.Invoke((Action)delegate {
        //Code in here will run in the STA thread
       label1.Text = "Test";
    });
});