C# - 大约30秒后形成冻结 - 多线程

时间:2017-09-02 16:52:51

标签: c# multithreading forms freeze

我目前正在开发一个包含两个表单和一个托盘图标的项目。但是,我在显示第二个表单Form2时遇到问题,它在以某种方式显示之后大约冻结了30秒。

第一种形式(Form1)始终显示在背景中,只有两个细红色按钮覆盖用户监视器两侧约7个像素,其间的空间是透明的。按钮用于在闹钟响起时闪烁,并且使用下面的代码成功完成。

运行此任务后,将创建一个新的Form2。 Form2显示有关正在关闭的警报的信息并允许确认,这也会阻止红条闪烁。在Form1的不透明度任务运行之后创建Form2。以下代码是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]);
            }));
        }

创建两个表单后,我有一个类,即在BackgroundWorker(bgUpdater)上运行的Updater,它会每10秒从Web API获取一个警报列表,然后生成这个成员公开在同类中。 Form2有一个BackgroundWorker本身,然后在另外10秒的时间间隔内从Updater中提取此成员,并使用它创建可点击的标签并在其表单中显示有关每个当前警报的信息。

更新程序具有在检测到警报时发送Toast通知的功能,并且具有将Form2打开到可以发送确认的正确页面的按钮。 Toast通知按钮的单击事件运行以下方法将表单打开到正确的页面:

    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()
        }

    }

仅通过正常打开表单(Form2.Activate())显示Form2时,没有问题,表单不会冻结,但是当使用ShowManagementUI(结果监视器)显示表单时,Form2会在10-之后的任何地方冻结30秒,但Form1继续闪烁红色条。它没有抛出任何异常,但我感觉它可能试图在UI线程上调用一个操作,但它因某种原因而被锁定。

我不能为我的生活找到为什么会这样做。有没有人对跟踪这样的冻结有任何建议?

1 个答案:

答案 0 :(得分:0)

在不透明度增加for循环中调用Application.DoEvents,以便为UI线程提供呈现更改的机会。间隔50ms也很小。尝试更大的数字。

但一般来说,这对动画来说不是一个好主意:P