开发者

System.Timers.Timer freezes when UI thread freezes in Windows XP

Hello.

You most likely are aware that a System.Windows.Forms.Timer freezes its action when the user interface thread also freezes, that happens because they run in the same thread.

That forced me to use a System.Timers.Timer which in turn if the user interface freezes the Timer continues to run its usual process like nothing ever happen.

Well my application does a allot of work with IE, and from time to time IE freezes when browsing a website with bad Javascript code. In consequence that also freezes my application user interface along with all the application, because everything in my application runs on the same Thread. To counteract that problem, my application from time to time runs a simple check on IE process's to see if they are still responding and if they don't they are terminated, all that on another Thread.

This counteraction runs perfect on Windows 7 32 bits, however when i run my application on a Windows XP machine that counteraction has no effect, maybe because my System.Timers.Timer also freezes when the user interface freezes. Which it shouldn't happen once its executed on another Thread like it doesn't happen on Windows 7.

Here is the code for the counteraction process

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 开发者_StackOverflow= 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 { }
        }
    }
}

This code is pretty simple. We have a Timers.Timer running every 15 seconds, once its time elapses a method is executed which in turn runs the delegate of a static method on another Thread which is responsible to terminate IE if he isn't responding.

How can i get this code to run well on Windows XP like it runs on Windows 7.

Any help is appreciated.

Thanks.

EDIT:

I also tried a System.Threading.Timer same result, in Windows 7 works but not in Windows XP.

EDIT: Following Kevin Gale advice:

I've attempted using only the Thread to run my counteraction, and i have found that it isn't the Thread it self that isn't working. Its the Process.Responding property that isn't working well in Windows XP.

New Code:

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();
}

This way the Thread is executed every 15 seconds on both Windows 7 and XP. But the reason i thought it wasn't working, was because he didn't close IE when it was unresponsive.

And I've found he didn't closed IE because according to exe.Responding which resolves if the process is responding or not, in Windows 7 he detects that IE isn't responding and in Windows XP it say that IE is responding although in fact it isn't. Thats why in XP the Thread didn't closed IE, and there so i thought the Thread didn't work.

So after all. The problem is how can i find if the process iexplore.exe is actually responding or not without using the Process.Responding property?

Info: The property Process.Responding in order to know if the process is responding requires the Process.MainWindowHandle property, which for some reason according to this code sample, in Windows 7 that property exists but not in Windows XP, there so Process.Responding also doesn't work on XP. Anybody knows a workaround?

Aftermath: Considering that my question it self has been answered, i will award the one responsible to truly helping me finding what was really the problem. The question for that problem continues here.

Thanks everyone.


Why use a timer at all. Just start the second thread and have it check every 15 seconds. That would be simpler and lower overhead.

But if you want to keep the timer maybe the System.Threading.Timer class might get around the problem.


Windows 7 made some major changes in thread safety for handling of system resources (like going from table locking to row locking in SQL). You're probably seeing contention for some system resource that blocks in XP but allows multiple accesses in Win7. Given that, it's not going to matter what thread your timer is running on because all of the threads will block on the same resource.

Maybe if you detect that this has happened in your app you could pop up a message suggesting the user upgrade their OS. :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜