【问题标题】:C#/Winforms App freezing/laggingC#/Winforms 应用程序冻结/滞后
【发布时间】:2011-02-24 15:43:17
【问题描述】:

我有一个 C#/Winforms 中的应用程序,它基本上用于以特定顺序/设置为客户帐户运行测试。它们都是在浏览器中运行的测试,所以我构建了它以便它可以自动执行该过程,因为每次启动客户帐户时都需要运行大约 10-12 个测试。

基本上会发生什么是您输入帐号然后它运行测试。

这是一个示例代码。

public void startTestProcess()
    { 
        if (!cancelTests)
        {
            testRunning = true;
            var tabPage = createTabPage(banToRun, Convert.ToInt32(banToRun));
            loadingBox.Visible = true;
            mainTabControl.TabPages.Insert(0, tabPage);
            mainTabControl.SelectedTab = mainTabControl.TabPages[0];
            runTest(tabPage, banToRun);
            loadingBox.Visible = false;
        }
    }

private void runTest(TabPage t, string ban)
    {
        if (!cancelTests && !cancelCurrentOnly)
        {
            var tC = createInitialTabControl();
            t.Controls.Add(tC);
            int[] theTests = profileInfo.getSetList;
            for (int i = 0; i < theTests.Length; i++)
            {
                if (!cancelTests && !cancelCurrentOnly)
                {
                    var newTab = createTabPage(urlStrings.getName(theTests[i]), theTests[i]);
                    tC.TabPages.Add(newTab);
                    var webBrowser = createBrowser(urlStrings.getUrl(theTests[i], ban));
                    newTab.Controls.Add(webBrowser);
                    if (theTests[i] != 0 && theTests[i] != 1 && theTests[i] != 6
                        && theTests[i] != 11 && theTests[i] != 12)
                    {
                        if (!webBrowser.IsDisposed)
                        {
                            try
                            {
                                while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
                                {
                                    Application.DoEvents();
                                }
                            }
                            catch
                            {
                                //Do Nothing
                            }
                        }
                    }
                    IntPtr pHandle = GetCurrentProcess();
                    SetProcessWorkingSetSize(pHandle, -1, -1);
                }
            }
        }
        if (cancelCurrentOnly)
        {
            cancelCurrentOnly = false;
        }
        banToRun = string.Empty;
        testRunning = false;

    }

所以基本上我的问题是,我怎样才能优化我所拥有的

A.减少延迟/冻结 - 注意:已经实现了在每次测试运行后强制进行垃圾收集的方法。 B. 可能提高 WebBrowser 控件的性能? - 已经尝试了一些 webbrowser 替代品,如用于 C# Wrapper 的 WebKit(由于我相信一些基于 ajax 的编码,不适用于所有测试) C. 也许实现多线程操作。不知道如何在不抛出跨线程异常的情况下解决这个问题。

感谢您的帮助。如果您有任何其他问题,请随时提出。

【问题讨论】:

    标签: c# winforms freeze multithreading lag


    【解决方案1】:

    延迟/冻结问题是由您使用多个线程引起的;因此所有的测试运行都在使用 UI 线程,因此在运行测试时 UI 无法响应。

    如果您不使用后台工作人员的原因是您担心引发跨线程异常,那么您只需要确保您在线程之间正确传递信息(而不是避免多线程完全)。

    更新

    This 问题解决了根据工作人员的进度更新 UI 的问题。

    附带说明,您不必强制进行垃圾收集;大多数情况下,这实际上会降低性能。垃圾收集器专门设计用于在有空时进行收集(当 CPU 可用时)。强制它运行会使您的应用程序尝试执行的实际工作花费周期。

    【讨论】:

    • 我希望是这样,如果我不强制垃圾收集应用程序实际上会陷入困境......很多。在这些 Web 浏览器控件上运行的测试实际上是非常密集的测试,所以我在浏览器完成加载后强制它以提高性能。
    • @Alex:您正在加载的页面大小是多少?运行它的机器有多少内存?
    • 不确定页面的大小,但它可以在多台机器(大约 500 台左右)上运行,每台机器 2gb(可能更多)
    • @Alex:如果您不确定如何进行多线程处理,请考虑使用 BackgroundWorker 控件。我敢打赌,如果你更好地开始 Dispose()ing 对象,你的垃圾收集问题就会消失。特别是,您是否确保正确处理您的 WebBrowser 对象?
    • 我添加了一个后台工作者,它确实加快了速度。我不确定如何使用 UI 元素来实现它,但我发现了如何使用调用。 object.Invoke((MethodInvoker)delegate { blah });
    【解决方案2】:

    我看到在处理 GUI 的方法中执行了很多繁重的工作,因此我假设所有这些都是在应用程序的主线程中完成的(在执行与该 WebBrowser 相关的非图形操作时会阻塞,并且其他领域)。

    尝试重构此应用程序以在多个线程中运行。主线程应该尽可能地可用以响应用户事件。后台线程应该负责创建昂贵的对象、执行长时间运行的读/写操作等。

    【讨论】:

    • 我同意,但是创建这些在循环中创建的对象必须在 GUI 线程中创建,否则我无法将控件添加到 GUI。所以我的问题是,我想我可以将这个测试代码的哪一部分移到后台线程中是我想要得到的。
    • 我会考虑将所有这些逻辑(涉及循环和测试运行)移动到工作线程中,当需要更新 GUI 时,使用 Control.Invoke() 或 BeginInvoke() 方法只在 UI 线程上执行 GUI 操作。随着工作线程中的循环返回,主线程应该保持足够活跃,以响应编程和用户更新 UI 的请求。
    猜你喜欢
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    相关资源
    最近更新 更多