一千萬個為什麽

搜索

當UI線程在Windows XP中凍結時,System.Timers.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秒運行一次,一旦執行了一個方法,該方法又運行靜態方法的委托 在另一個 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沒有用。

所以畢竟。問題是如何在不使用 Process.Responding 屬性的情況下找到進程 iexplore.exe 是否實際響應?

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.

感謝大家。

最佳答案

為什麽要使用計時器。只需啟動第二個線程並每隔15秒檢查一次。這將更簡單,開銷更低。

但是如果你想保留定時器,那麽System.Threading.Timer類可能會解決問題。

轉載註明原文: 當UI線程在Windows XP中凍結時,System.Timers.Timer會凍結