Я написал программу на C#, которая включает несколько глобальных горячих клавиш и на основе нажатой горячей клавиши, она активирует окна, такие как хром, firefox, блокнот, калькулятор и т. Д. После регистрации глобальных горячих клавиш, У меня есть бесконечный цикл while, который поддерживает приложение. После запуска программы внезапно горячие клавиши перестают работать. Это происходит через несколько часов. После долгого тестирования каждого фрагмента моего кода я нашел проблему. Проблема в том, что внезапно главный поток перестает работать. Программа все еще жива и в памяти. Горячие клавиши, кажется, зарегистрированы в другом потоке, который является живым, и поддерживает работу программы, даже когда основной поток, содержащий цикл while, мертв.C# backgroundworker останавливается сам по себе
Затем я использовал фонового работника и перемещал цикл while в фоном. Это произошло снова, что означает, что фоновая работа внезапно прекратилась, пока горячие клавиши все еще зарегистрированы. Это не мой первый раз, когда я использовал backgroudworker, и я никогда не сталкивался с чем-то подобным, что фоновая работа выходит сама собой.
Когда это происходит, сообщения, подобные этому, появились в выходных окнах Visual Studio:
The thread 0x1b24 has exited with code 0 (0x0)
Есть ли какие-либо временные ограничения для потоков, так что они будут выходить после этого? Есть ли у вас какие-либо предположения о том, как это происходит и как я могу это исправить?
Для глобальных сочетаний клавиш, я использую код, приведенный здесь:
http://stackoverflow.com/a/3654821/3179989
и это остальная часть моего кода:
public static void HotKeyPressed(object sender, HotKeyEventArgs e)
{
string PressedHotkey = e.Modifiers.ToString() + " " + e.Key.ToString();
switch (PressedHotkey)
{
case "Alt D1":
mActivateWindow(mEnumApplications.Chrome);
break;
case "Alt D3":
mActivateWindow(mEnumApplications.CintaNotes);
break;
default:
break;
}
}
private void button1_Click(object sender, EventArgs e)
{
bgWkrHotkey.WorkerSupportsCancellation = true;
bgWkrHotkey.WorkerReportsProgress = true;
bgWkrHotkey.RunWorkerAsync();
}
private void bgWkrHotkey_DoWork(object sender, DoWorkEventArgs e)
{
mHotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Alt);
mHotKeyManager.RegisterHotKey(Keys.D1, KeyModifiers.Alt);
mHotKeyManager.RegisterHotKey(Keys.D3, KeyModifiers.Alt);
mHotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyPressed);
while (true)
{
Thread.Sleep(50);
}
}
//@@@@@@@@@@@@@@@@@@@@ DLL IMPORTS @@@@@@@@@@@@@@@@@@@@
#region DLL IMPORTS
[DllImport("User32.dll")]
private static extern IntPtr SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("USER32.DLL")]
static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("USER32.DLL")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("USER32.DLL")]
static extern IntPtr GetShellWindow();
#endregion DLL IMPORTS
public static IDictionary<IntPtr, string> mGetOpenWindows()
{
IntPtr ipShellWindow = GetShellWindow();
Dictionary<IntPtr, string> ipWindows = new Dictionary<IntPtr, string>();
EnumWindows(delegate(IntPtr hWnd, int lParam)
{
if (hWnd == ipShellWindow) return true;
//if (!IsWindowVisible(hWnd)) return true;
int lLength = GetWindowTextLength(hWnd);
if (lLength == 0) return true;
StringBuilder lBuilder = new StringBuilder(lLength);
GetWindowText(hWnd, lBuilder, lLength + 1);
ipWindows[hWnd] = lBuilder.ToString();
return true;
}, 0);
return ipWindows;
}
public static string mGetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return "";
}
public static bool mActivateWindow(IntPtr ipHandle, string strWindowTitle)
{
StringBuilder Buff = new StringBuilder(256);
SetForegroundWindow(ipHandle);
Stopwatch swTimeout = new Stopwatch();
swTimeout.Start();
while (swTimeout.Elapsed < TimeSpan.FromSeconds(2))
{
ipHandle = GetForegroundWindow();
if ((GetWindowText(ipHandle, Buff, 256) > 0) && (Buff.ToString().ToLower().Contains(strWindowTitle.ToLower())))
return true;
else
{
SetForegroundWindow(ipHandle);
Thread.Sleep(50);
}
}
swTimeout.Stop();
return false;
}
public static bool mActivateWindow(mEnumApplications enumApp)
{
string strWindowTitle = "";
switch (enumApp)
{
case mEnumApplications.Chrome:
strWindowTitle = "Google Chrome";
break;
case mEnumApplications.CintaNotes:
strWindowTitle = "CintaNotes";
break;
default:
break;
}
IntPtr ipHandle = IntPtr.Zero;
string strExactTitle = "";
StringBuilder Buff = new StringBuilder(256);
foreach (KeyValuePair<IntPtr, string> ipWindow in mGetOpenWindows())
{
ipHandle = ipWindow.Key;
strExactTitle = ipWindow.Value;
if (strExactTitle.ToLower().Contains(strWindowTitle.ToLower()))
if (mActivateWindow(ipHandle, strWindowTitle))
return true;
}
return false;
}
public enum mEnumApplications
{
Null,
Chrome,
CintaNotes,
};
Я признателен за любую помощь. Thanks
У вас был необъяснимый сбой в вашей основной теме, поэтому вы переместили горячие клавиши в «BackgroundWorker»? Похоже, вы должны были диагностировать, что авария в главном потоке. Перемещение к «BackgroundWorker» просто удвоило (по крайней мере) проблему. Тем не менее, я подозреваю, что что-то в вашем горячем ключе нажал обработчик бросает исключение. Положите попытку/поймать его и запишите любое исключение, которое вы получите. –
Кроме того, я бы внимательно посмотрел на ваш обратный вызов «EnumWindows». Выделение памяти для вашего 'StringBuilder' является подозрительным, тем более, что вы назначаете его' lLength', но затем передаете 'lLength + 1' в' GetWindowText'. Это может очень хорошо попытаться перезаписать память, которой у вас нет, и вызвать сбой потока. 'GetWindowTextLength' не зависит от того, включает ли возвращаемое значение нулевой ограничитель. Вполне возможно добавление 1 к возвращаемому значению и использование результата для инициализации вашего 'StringBuilder' решит проблему. –
Спасибо за ваши комментарии. Эта часть кода на самом деле не является моим собственным кодом, и я просто скопировал из Интернета (http://blog.tcx.be/2006/05/getting-list-of-all-open-windows.html). Извините, я должен был процитировать это в моем главном сообщении. Не могли бы вы изменить код и отправить его в качестве ответа, поскольку я не совсем уверен, что вы имеете в виду? Спасибо – NESHOM