2010-08-17 238 views
0

Hello。当Windows XP中的UI线程冻结时System.Timers.Timer冻结

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

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

那么我的应用程序做了一个与IE浏览器的工作分配,并不时浏览一个网站的Javascript代码糟糕的IE浏览器冻结。因此,也会冻结我的应用程序用户界面以及所有应用程序,因为我的应用程序中的所有内容都运行在相同的Thread上。为了解决这个问题,我的应用程序不时地对IE进程进行一次简单的检查,看看它们是否仍在响应,如果它们没有被终止,那么在另一个线程上。

这种反作用在Windows 7 32位上运行完美,但是当我在Windows XP计算机上运行我的应用程序时,反作用没有效果,可能是因为我的System.Timers.Timer也在用户界面冻结时冻结。这就像它不会在Windows 7

发生不应一旦其另一Thread执行发生下面是反作用过程

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 { } 
     } 
    } 
} 

这段代码是非常简单的代码。我们有一个每15秒运行一次的Timers.Timer,一旦它的时间流逝,一个方法被执行,然后在另一个Thread上运行delegatedelegate,如果他没有响应,该方法负责终止IE。

我怎样才能得到这个代码,像它可以运行在Windows 7

任何帮助表示赞赏在Windows XP上运行良好。

谢谢。

编辑:

我也尝试了System.Threading.Timer相同的结果,在Windows 7的作品,但不能在Windows XP。

编辑:继凯文·盖尔建议:

我只用线程来运行我的反作用尝试,我发现它是不是它的线程自认为是行不通的。它的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(); 
} 

这样线程每15秒运行于Windows 7和XP两个。但是我认为它不起作用的原因是因为他在没有响应时没有关闭IE。

我发现他没有关闭IE,因为根据exe.Responding它解决了进程是否响应,在Windows 7中,他检测到IE没有响应,并且在Windows XP中它说IE正在响应尽管事实上并非如此。这就是为什么在XP线程没有关闭IE浏览器,所以我认为线程无法正常工作。

因此毕竟。问题是我如何才能找到过程iexplore.exe实际上是否响应或不使用Process.Responding属性?

信息:酒店Process.Responding为了知道该进程是否响应要求Process.MainWindowHandle属性,它由于某种原因,根据这个代码sample,在Windows 7中,物业存在,但不能在Windows XP中,有这么Process.Responding也不适用于XP。任何人都知道解决方法?

后果:考虑到我自己的问题已经得到解答,我将授予一个负责任的人,真正帮助我找到真正的问题。该问题的问题继续here

谢谢大家。

回答

4

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

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

+0

我第二个专用线程的想法。如果'System.Threading.Timer'没有遇到同样的问题,我会感到惊讶。最后,它基本上是'System.Timers.Timer'的主干。 – 2010-08-17 21:25:56

+0

我倾向于同意Threading.Timer这只是一些尝试。 – 2010-08-17 21:29:11

+0

永远不会受伤:) – 2010-08-17 21:34:37

1

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

也许如果您检测到在您的应用中发生了这种情况,您可能会弹出消息,提示用户升级其操作系统。 :)

+0

@Jonh Bowen:这个应用程序将运行在大量运行XP的虚拟机中。它是在XP中工作的。没有解决方法。 – 2010-08-18 00:26:12