Вероятно, для того же, логичного, который делает это не ошибкой:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
Это вообще невозможно. Возьмем, к примеру, обычное приложение - текстовый процессор. В настоящее время он будет запускать проверку орфографии в фоновом режиме, он периодически автоматически сохраняет ваш документ и т.д. Тем не менее, с точки зрения пользователей, он все время ждет ввода.
Другой распространенный случай - программа просмотра слайд-шоу. В любой момент времени вы можете нажать клавишу, чтобы продвинуть слайд. Тем не менее, ваш обычный пользователь не будет рассматривать это как «ожидание ввода».
Подводя итог: «ожидание ввода» является субъективным состоянием и поэтому не может быть определено программно.
Как вам это нравится?
Я разработал решение, которое, похоже, работает, пожалуйста, сообщите мне в случае проблем с этим кодом, чтобы я также получил преимущества от улучшений. Насколько я тестировал, он работает в Excel. Единственная проблема, которая мне не нравится, - это то, что мне приходилось использовать неуправляемые вызовы. Он также обрабатывает случай, когда приложение основано на диалоговом окне, например, для MFC, производном от CDialog.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
namespace Util
{
public class ModalChecker
{
public static Boolean IsWaitingForUserInput(String processName)
{
Process[] processes = Process.GetProcessesByName(processName);
if (processes.Length == 0)
throw new Exception("No process found matching the search criteria");
if (processes.Length > 1)
throw new Exception("More than one process found matching the search criteria");
// for thread safety
ModalChecker checker = new ModalChecker(processes[0]);
return checker.WaitingForUserInput;
}
#region Native Windows Stuff
private const int WS_EX_DLGMODALFRAME = 0x00000001;
private const int GWL_EXSTYLE = (-20);
private delegate int EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("user32")]
private extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private extern static uint GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private extern static uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
#endregion
// The process we want the info from
private Process _process;
private Boolean _waiting;
private ModalChecker(Process process)
{
_process = process;
_waiting = false; //default
}
private Boolean WaitingForUserInput
{
get
{
EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
return _waiting;
}
}
private int WindowEnum(IntPtr hWnd, int lParam)
{
if (hWnd == _process.MainWindowHandle)
return 1;
IntPtr processId;
GetWindowThreadProcessId(hWnd, out processId);
if (processId.ToInt32() != _process.Id)
return 1;
uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
if ((style & WS_EX_DLGMODALFRAME) != 0)
{
_waiting = true;
return 0; // stop searching further
}
return 1;
}
}
}
Если я вас хорошо понимаю, вы можете попробовать перечислить потоки процесса и проверить их состояние. Диспетчер задач Windows делает нечто подобное. Однако для этого потребуются функции Win32, среди которых Thread32First и Thread32Next, но вы можете добиться этого с помощью простейшего использования P / Invoke в C #:
[DllImport("Executor.dll")]
public static extern bool Thread32First(IntPtr handle, IntPtr threadEntry32);
(Точная подпись может отличаться).
EDIT: Хорошо, есть соответствующие функции в библиотеке .NET.
Если возможно, перепишите другой код, чтобы он был процессором одновременного ввода (аналогично алгоритму для параллельного веб-сервера):
Wait for input
Fork process
Parent: Repeat
Child: (Worker) handle input
Конечно, у вас все еще может быть ваша функция:
static Boolean IsWaitingForUserInput(String processName) {
return true;
}