System.Timers.Timer зависает при зависании потока пользовательского интерфейса в Windows XP - PullRequest
0 голосов
/ 18 августа 2010

Здравствуйте.

Скорее всего, вы знаете, что System.Windows.Forms.Timer останавливает свое действие, когда поток пользовательского интерфейса также останавливается, что происходит потому, что они выполняются в одном потоке.

Это заставило меня использовать System.Timers.Timer, который, в свою очередь, если пользовательский интерфейс зависает, Timer продолжает работать как обычно, ничего не происходит.

Что ж, мое приложение выполняет много работыс IE, и время от времени IE зависает при просмотре веб-сайта с плохим кодом Javascript.В результате это также замораживает пользовательский интерфейс моего приложения вместе со всем приложением, потому что все в моем приложении работает на том же 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.

РЕДАКТИРОВАТЬ: Следуя советам Кевина Гейла:

Я пытался использовать только Нить, чтобы запустить свое противодействие, и я обнаружил, что не сам Нить не работает.Свойство 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.Кто-нибудь знает обходной путь?

Последствия : Учитывая, что на мой вопрос сам был дан ответ, я вознагражу ответственного за то, что он действительно помог мне найти то, что действительно было проблемой.Вопрос для этой проблемы продолжается здесь .

Спасибо всем.

Ответы [ 2 ]

4 голосов
/ 18 августа 2010

Зачем вообще использовать таймер. Просто запустите второй поток и проверяйте его каждые 15 секунд. Это было бы проще и дешевле.

Но если вы хотите сохранить таймер, возможно, класс System.Threading.Timer может обойти эту проблему.

1 голос
/ 18 августа 2010

Windows 7 внесла некоторые значительные изменения в безопасность потоков для обработки системных ресурсов (например, переход от блокировки таблиц к блокировке строк в SQL). Возможно, вы столкнулись с конкуренцией за какой-то системный ресурс, который блокирует в XP, но допускает множественный доступ в Win7. Учитывая это, не имеет значения, в каком потоке работает ваш таймер, потому что все потоки будут блокироваться на одном ресурсе.

Возможно, если вы обнаружите, что это произошло в вашем приложении, вы можете получить сообщение, предлагающее пользователю обновить свою ОС. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...