当UI线程在Windows XP中冻结时,System.Timers.Timer会冻结

时间:2010-08-17 20:52:05

标签: c# multithreading timer

你好。

当用户界面线程也冻结时,你很可能知道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秒运行一次,一旦执行了一个方法,该方法又会在另一个负责终止的delegate上运行static method Thread IE,如果他没有回应。

如何让这段代码在Windows XP上运行良好,就像在Windows 7上运行一样。

感谢任何帮助。

感谢。

修改

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

编辑:关注Kevin Gale的建议:

我试图只使用Thread来运行我的反作用力,而且我发现它不是自己的线程不能正常工作。它的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秒执行一次Thread。但我认为它不起作用的原因是因为当它没有响应时他没有关闭IE。

我发现他没有关闭IE,因为根据exe.Responding解析了进程是否响应,在Windows 7中他检测到IE没有响应,而在Windows XP中它说IE正在回应,但实际上并非如此。这就是为什么在XP中​​Thread没有关闭IE,所以我认为Thread没有用。

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

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

后果:考虑到我自己的问题已得到回答,我会授予负责人真正帮助我找到真正的问题。该问题的问题仍在继续here

谢谢大家。

2 个答案:

答案 0 :(得分:4)

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

但是如果你想保留计时器,那么System.Threading.Timer类可能会解决问题。

答案 1 :(得分:1)

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

如果您发现在您的应用中发生了这种情况,您可能会弹出一条消息,建议用户升级其操作系统。 :)