2015-09-14 3 views
0

Должно ли KillTimer быть вызвано тем же процессом указанного таймера?KillTimer - Неожиданно уничтожить таймер другого процесса

+0

@ user1 https://msdn.microsoft.com/en-us/library/windows/desktop/ms644903%28v=vs.85%29.aspx ничего о разрушении таймера другого процесса. – RepeatUntil

+1

Документы 'SetTimer' понятны, что' hWnd' должен принадлежать вызывающему потоку. Весьма вероятно, что такое же ограничение применимо и к KillTimer. –

+0

Я не совсем уверен, что термин «непреднамеренно» должен означать в этом контексте. Вы хотите «случайно» убить таймер? –

ответ

3

Да, KillTimerдолжен быть вызван тем же процессом, что и тот, который называется SetTimer. Однако, несмотря на то, что в документации ясно, что вызывающему потоку необходимо владеть окном при вызове SetTimer, похоже, что для KillTimer такое же правоприменение не применяется. Он даже не говорит, что убийца должен быть одним и тем же процессом, не говоря уже о том же потоке. Таким образом, то, что должно было произошло и что должно произошло, это две разные вещи.

Raymond Chen wrote in his blog in 2012 about killing timers, а в комментариях несколько заявлений, в которых утверждается, что таймеры могут быть убиты только из первоначального процесса. Эти утверждения остаются неоспоримыми, но экспериментально их легко опровергнуть.

Следующая программа из командной строки показывает, что можно убить таймеры из других процессов. Запустите его один раз без аргументов, и он создает таймер и начинает печатать сообщения с идентификатором таймера. Передайте этот идентификатор второму вызову программы и второй экземпляр убьет таймер первого экземпляра. Он сообщит об успехе, и первый экземпляр остановит печать сообщений (потому что он больше не принимает сообщения таймера).

#include <iostream> 
#include <sstream> 
#include <windows.h> 

int main(int argc, char* argv[]) 
{ 
    if (argc > 1) { 
     std::istringstream in(argv[1]); 
     UINT timerid; 
     in >> timerid; 
     if (!KillTimer(NULL, timerid)) { 
      DWORD err = GetLastError(); 
      std::cout << "KillTimer error (" << err << ")" << std::endl; 
     } 
     else { 
      std::cout << "KillTimer success" << std::endl; 
     } 
    } else { 
     UINT timerid = SetTimer(NULL, 0, 1000, NULL); 
     std::cout << "Get timer ID " << timerid << std::endl; 
     MSG msg; 
     while (GetMessage(&msg, NULL, 0, 0)) { 
      if (msg.message == WM_TIMER) { 
       std::cout << "Got WM_TIMER " << msg.wParam << std::endl; 
      } 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 
    return 0; 
} 

(процессы были 32 бита, работающие на 64-битной Windows 7 VM, скомпилированные с Visual Studio 2015, потому что это то, что у меня есть. Эквивалентный код на любом другом языке, должны быть легко повторить.)