简体   繁体   English

C#-大约30秒后冻结表格-多线程

[英]C# - Form freezing after about 30 seconds - Multithreading

I'm currently working on a project with two forms and a tray icon. 我目前正在一个具有两个表单和一个托盘图标的项目中。 However I'm having trouble when displaying the second form, Form2, that it simply freezes about 30 seconds after being displayed in a certain way. 但是,当显示第二个窗体Form2时,我遇到了麻烦,即它只是以某种方式显示大约30秒后就冻结了。

The first form (Form1) is always displayed in the background, with only two thin red buttons covering about 7 pixels on each side of the user's monitor and the space in between is transparent. 第一种形式(Form1)始终显示在背景中,只有两个细的红色按钮在用户监视器的每一侧覆盖大约7个像素,并且它们之间的空间是透明的。 The buttons are meant to flash when an alarm is going off and they do so successfully using the code below. 当警报响起时,这些按钮将闪烁,并使用下面的代码成功闪烁。

After this Task is run, a new Form2 is created. 运行此任务后,将创建一个新的Form2。 Form2 displays information about the alarm that is going off and allows acknowledgement, which also stops the red bars from flashing. Form2显示有关即将关闭的警报的信息,并允许进行确认,这也使红色条停止闪烁。 Form2 is created just after Form1's Opacity task is run. 在运行Form1的不透明度任务后立即创建Form2。 The below code is the Main function of Program.cs 下面的代码是Program.cs的主要功能

        redBarForms = new List<Form1>();
        foreach (var screen in Screen.AllScreens)
        {
            var form = new Form1();
            form.Opacity = 0d;
            form.Show();

            form.WindowState = FormWindowState.Normal;
            form.Location = screen.WorkingArea.Location;
            form.WindowState = FormWindowState.Maximized;

            redBarForms.Add(form); // Only one is added right now, working from one screen
        }

        // Begin the loop which checks to see if the bars should be flashing. 
        Task.Run(() =>
        {
            while (true)
            {
                while (flashingAlertBars)
                {
                    for (int i = 1; i <= 100; i++)
                    {
                        foreach (var form in redBarForms)
                        {
                            form.Invoke(new Action(() =>
                            {
                                form.Opacity = i / 100d;
                            }));
                            i += 9;
                        }
                        Thread.Sleep(50);
                    }

                    for (int i = 100; i >= 1; i--)
                    {
                        foreach (var form in redBarForms)
                        {
                            form.Invoke(new Action(() =>
                            {
                                form.Opacity = i / 100d;
                            }));
                            i -= 9;
                        }
                        Thread.Sleep(50);
                    }
                }
            }
        });

        MainForm = new Form2();

        // Start the updater on a background worker so that it doesn't 
           affect the UI thread
        BackgroundWorker bgUpdater = new BackgroundWorker();
        bgUpdater.WorkerSupportsCancellation = true;
        bgUpdater.DoWork += Updater_BGWorker_DoWork;
        bgUpdater.RunWorkerAsync();

        // Start Form1
        if (!redBarForms[0].IsDisposed)
        {
            redBarForms[0].Invoke(new Action(() =>
            {
                Application.Run(redBarForms[0]);
            }));
        }

After both forms are created, I've got a class, Updater, that is run on a BackgroundWorker (bgUpdater), which gets a list of which alarms are going off from a web API every 10 seconds, then makes this member public in its class. 创建这两种形式后,我有一个在Updateer上运行的类,该类在BackgroundWorker(bgUpdater)上运行,该类每10秒从Web API发出警报的列表,然后将该成员公开类。 Form2 has a BackgroundWorker itself that then pulls this member from Updater on another 10 second interval and uses it to create clickable labels and display information about each current alarm in its form. Form2本身具有BackgroundWorker,然后在另一个10秒间隔内将其从Updater中拉出,并使用它来创建可单击的标签并以其形式显示有关每个当前警报的信息。

Updater has a feature to send a toast notification when an alarm is detected, and has a button to open Form2 to the correct page where an acknowledgement can be sent. Updater具有在检测到警报时发送烤面包通知的功能,并且具有将Form2打开到可以发送确认的正确页面的按钮。 The toast notification button's click event runs the following method to open the form to the correct page: 吐司通知按钮的click事件运行以下方法以将表单打开到正确的页面:

    static public void ShowManagementUI(Result monitor)
    {
        if (Application.OpenForms.OfType<Form2>().Count() > 0)
        {
            if (MainForm.InvokeRequired)
            {
                MainForm.Invoke(new Action(() =>
                {
                    MainForm.ShowWithResult(monitor); //This just does an Activate()
                }));
            }
        }
        else
        {
            if (MainForm.IsDisposed)
                MainForm = new Form2();
            MainForm.Show();
            MainForm.ShowWithResult(monitor); //This just does an Activate()
        }

    }

When displaying Form2 just by opening the form normally (Form2.Activate()), there is no issue and the form does not freeze, however when displaying the form using ShowManagementUI(Result monitor), Form2 freezes after anywhere between 10-30 seconds, but Form1 keeps on flashing its red bars. 仅通过正常打开窗体(Form2.Activate())来显示Form2时,没有问题,窗体也不会冻结,但是当使用ShowManagementUI(Result Monitor)显示窗体时,Form2会在10到30秒之间的任何时间冻结,但是Form1一直闪烁其红色条。 It doesn't throw any exceptions, but I have a feeling it's probably attempting to Invoke an operation on the UI thread but it's locked for one reason or another. 它不会引发任何异常,但是我感觉到它可能正在尝试在UI线程上调用操作,但是由于某种原因或另一种原因它被锁定。

I cannot for the life of me find why it would be doing this. 我一生无法找到为什么会这样做。 Does anyone have any suggestions on tracking down a freeze like this? 有人对跟踪这样的冻结有任何建议吗?

Call Application.DoEvents in the opacity increasing for loop in order to give UI thread a chance to render changes. 调用不透明度增加的for循环中的Application.DoEvents ,以使UI线程有机会呈现更改。 Also 50ms interval is small. 50ms的间隔也很小。 Try bigger numbers. 尝试更大的数字。

But generally, this is not a good idea for animation :P 但这通常不是动画的好主意:P

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

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