简体   繁体   English

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

[英]c# - Form "lags" after button being pressed

I made a extension to a game that I made which automatically presses a button when you press "Search Pixel" But each time I press the button whether it succeeds or fails, the memory for the application rises by about 30 Mega Bytes.我对我制作的游戏进行了扩展,当您按下“搜索像素”时,它会自动按下一个按钮,但每次按下按钮时,无论成功还是失败,应用程序的内存都会增加大约 30 兆字节。 Starts at 4.5 MB then once the button is click, it rises to 33.3 MB here is the code从 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);
        }
    }
}

This code is from a video that I watched.此代码来自我观看的视频。 If you need me to do anything like post the video or post any other code just let me know please I really need help.如果您需要我做任何事情,例如发布视频或发布任何其他代码,请告诉我,我真的需要帮助。 I also wanna just say that I'm really new to coding in c#.我还想说,我对 C# 编码真的很陌生。

Explanation解释

Windows Forms uses a single threaded apartment model. Windows 窗体使用单线程单元模型。 This means everything in Windows Forms, from rendering to processing Windows messages (like mouse and keyboard events), occurs in a single thread.这意味着 Windows 窗体中的所有内容,从呈现到处理 Windows 消息(如鼠标和键盘事件),都发生在单个线程中。

You may have noticed in all of your WinForms applications you can see a [STAThreadAttribute] in your Program.cs .您可能已经注意到,在所有 WinForms 应用程序中,您都可以在Program.cs看到[STAThreadAttribute] The 'STA' stands for 'Single Thread Apartment'. “STA”代表“单线程公寓”。

Because WinForms runs in a single thread apartment, any intensive code you run in your WinForms STA thread will block WinForms from rendering your form and processing its mouse and keyboard events as it's only able to do one thing at a time.因为 WinForms 在单线程单元中运行,所以您在 WinForms STA 线程中运行的任何密集代码都会阻止 WinForms 呈现您的表单并处理其鼠标和键盘事件,因为它一次只能做一件事。

The solution解决方案

The solution here is to run your intensive SearchPixel() function in a separate thread to the WinForms STA thread.此处的解决方案是在 WinForms STA 线程的单独线程中运行您的密集SearchPixel()函数。

There are many ways to achieve this, such as a BackgroundWorker , or a hard Thread .有很多方法可以实现这一点,例如BackgroundWorker或 hard Thread However the easiest and most acceptable way would be to use a Task which is automatically deferred to a thread pool.然而,最简单,最容易被接受的方法是使用一个Task后自动推迟到一个线程池。

This is as simple as changing your code like so:这就像更改代码一样简单:

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

Caveat警告

As your code will be running in a thread other than WinForms' STA thread it is not possible to interact with any object that WinForms is using without doing an invoke.由于您的代码将在 WinForms 的 STA 线程以外的线程中运行,因此在不执行调用的情况下无法与 WinForms 正在使用的任何对象进行交互。

For example:例如:

Task.Run(() => {
    label1.Text = "Test";
});

Will cause an InvalidOperationException , as you're attempting to access an object that WinForms expects to only be accessed in its single thread apartment.将导致InvalidOperationException ,因为您正在尝试访问 WinForms 希望只能在其单线程单元中访问的对象。

You must tell the STA thread to invoke an action, which will cause the code to be run in the STA thread.您必须告诉 STA 线程调用一个操作,这将导致代码在 STA 线程中运行。 Like so:像这样:

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";
    });
});

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

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