你好。
当用户界面线程也冻结时,你很可能知道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。
谢谢大家。
答案 0 :(得分:4)
为什么要使用计时器。只需启动第二个线程并每隔15秒检查一次。这样会更简单,开销更低。
但是如果你想保留计时器,那么System.Threading.Timer类可能会解决问题。
答案 1 :(得分:1)
Windows 7对线程安全性进行了一些重大更改,以便处理系统资源(例如从SQL中的表锁定到行锁定)。您可能会看到争用一些在XP中阻塞的系统资源,但允许在Win7中进行多次访问。鉴于此,运行定时器的线程并不重要,因为所有线程都将在同一资源上阻塞。
如果您发现在您的应用中发生了这种情况,您可能会弹出一条消息,建议用户升级其操作系统。 :)