【问题标题】:System.Timers.Timer freezes when UI thread freezes in Windows XP当 UI 线程在 Windows XP 中冻结时 System.Timers.Timer 冻结
【发布时间】:2011-03-31 05:28:58
【问题描述】:

你好。

您很可能知道System.Windows.Forms.Timer 会在用户界面线程也冻结时冻结其操作,这是因为它们在同一个线程中运行。

这迫使我使用System.Timers.Timer,如果用户界面冻结,Timer 会继续运行其通常的进程,就像什么都没发生一样。

好吧,我的应用程序在 IE 上做了很多工作,当浏览一个带有错误 Javascript 代码的网站时,IE 有时会死机。结果,这也冻结了我的应用程序用户界面以及所有应用程序,因为我的应用程序中的所有内容都在同一个Thread 上运行。为了解决这个问题,我的应用程序不时对 IE 进程运行一个简单的检查,以查看它们是否仍在响应,如果没有响应,它们将被终止,所有这些都在另一个线程上。

这个反作用在 Windows 7 32 位上运行完美,但是当我在 Windows XP 机器上运行我的应用程序时,反作用没有效果,可能是因为我的System.Timers.Timer 在用户界面冻结时也会冻结。一旦在另一个 Thread 上执行它就不应该发生这种情况,就像它不会在 Windows 7 上发生一样。

这是反作用过程的代码

private System.Timers.Timer IEResponsiveCheckTimer = new System.Timers.Timer();

private void onLoad(object sender, EventArgs e)
{
    this.IEResponsiveCheckTimer.Interval = 15000;
    this.IEResponsiveCheckTimer.Elapsed += new System.Timers.ElapsedEventHandler(IEResponsiveCheck);
    this.IEResponsiveCheckTimer.Start();
}

private void IEResponsiveCheck(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(IEResponsiveChecker));
    t.Start();
}

static void IEResponsiveChecker()
{
    bool terminate = false;
    foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
    {
        if (exe.ProcessName.StartsWith("iexplore"))
        {
            if (exe.Responding == false)
            {
                terminate = true;
                break;
            }
        }
    }
    if (terminate == true)
    {
        foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
        {
            if (exe.ProcessName.StartsWith("iexplore"))
                try { exe.Kill(); }
                catch { }
        }
    }
}

这段代码非常简单。我们有一个Timers.Timer 每 15 秒运行一次,一旦它的时间过去了,就会执行一个方法,该方法反过来在另一个 Thread 上运行 delegateThread,如果他没有响应,它负责终止 IE。

我怎样才能让这段代码在 Windows XP 上像在 Windows 7 上一样运行良好。

感谢任何帮助。

谢谢。

编辑:

我也尝试了 System.Threading.Timer 相同的结果,在 Windows 7 中有效,但在 Windows XP 中无效。

编辑:遵循 Kevin Gale 的建议:

我尝试只使用线程来运行我的反作用,我发现不是线程本身不起作用。它的 Process.Responding 属性在 Windows XP 中无法正常工作。

新代码:

private void onLoad(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(IEResponsiveChecker));
    t.Start();
}

static void IEResponsiveChecker()
{
    bool terminate = false;
    foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
    {
        if (exe.ProcessName.StartsWith("iexplore"))
        {
            if (exe.Responding == false)
            {
                terminate = true;
                break;
            }
        }
    }
    if (terminate == true)
    {
        foreach (System.Diagnostics.Process exe in System.Diagnostics.Process.GetProcesses())
        {
            if (exe.ProcessName.StartsWith("iexplore"))
                try { exe.Kill(); }
                catch { }
        }
    }
    Thread.Sleep(15000);
    IEResponsiveChecker();
}

这样,线程在 Windows 7 和 XP 上每 15 秒执行一次。但我认为它不起作用的原因是因为他没有在 IE 无响应时关闭它。

我发现他没有关闭 IE,因为根据exe.Responding 解决进程是否响应,在 Windows 7 中他检测到 IE 没有响应,在 Windows XP 中它说 IE 是回应虽然事实上它不是。这就是为什么在 XP 中 Thread 没有关闭 IE,所以我认为 Thread 不起作用。

毕竟。问题是如何在不使用 Process.Responding 属性的情况下找到进程 iexplore.exe 是否实际响应?

信息: 属性Process.Responding 以了解进程是否响应需要Process.MainWindowHandle 属性,根据此代码sample 出于某种原因,在Windows 7 中该属性存在但在 Windows XP 中不存在,因此Process.Responding 也不适用于 XP。有人知道解决方法吗?

后果:考虑到我的问题本身已经得到解答,我将奖励真正帮助我找到真正问题的负责人。该问题的问题继续here

谢谢大家。

【问题讨论】:

    标签: c# multithreading timer


    【解决方案1】:

    Windows 7 对处理系统资源的线程安全性进行了一些重大更改(例如从 SQL 中的表锁定变为行锁定)。您可能会看到一些系统资源的争用,这些资源在 XP 中被阻止,但在 Win7 中允许多次访问。鉴于此,您的计时器在哪个线程上运行并不重要,因为所有线程都会阻塞在同一资源上。

    也许如果您检测到您的应用中发生了这种情况,您可能会弹出一条消息,建议用户升级他们的操作系统。 :)

    【讨论】:

    • @Jonh Bowen:此应用程序将在运行 XP 的大量 VM 中运行。它本来可以在 XP 中运行。没有解决方法。
    【解决方案2】:

    为什么要使用计时器。只需启动第二个线程并让它每 15 秒检查一次。这样会更简单,开销也更低。

    但如果你想保留计时器,也许 System.Threading.Timer 类可能会解决这个问题。

    【讨论】:

    • 我支持专用线程的想法。如果System.Threading.Timer 没有遇到同样的问题,我会感到惊讶。毕竟它基本上是System.Timers.Timer的骨干。
    • 我倾向于同意 Threading.Timer 这只是尝试的东西。
    • 我是 C# 线程的新手。您如何建议在不使用计时器的情况下完成此操作,并且仍然每 15 秒运行一次线程? @Brian Gideon:我会尝试使用 Threading.Timer,我可能会很幸运;)
    • 对不起,我没有尽快回复您,我看到其他问题已得到解答。我对上述编辑代码的唯一评论是您应该使用循环而不是递归调用 IEResponsiveChecker()。
    猜你喜欢
    • 1970-01-01
    • 2011-06-22
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    相关资源
    最近更新 更多