Я работаю с C # и .NET 4.0.
Моя программа состоит из внешнего интерфейса и внутреннего интерфейса. Серверная часть будет работать как служба Windows, которая запускается автоматически при запуске системы. Внешний интерфейс - это приложение WPF, которое пользователь запустит, когда будет готово к работе с приложением.
В рамках процесса запуска клиенту необходимо установить связь с серверной частью. Это делается с помощью XMPP и работает нормально. Код, выполняющий связь, имеет метод BeginStart, который возвращает WaitHandle. Внутри try-catch я вызываю BeginStart, получаю WaitHandle и вызываю метод WaitOne (TimeSpan) Waithandle. Обратите внимание, что в этот момент программа отображает заставку. И эти вызовы выполняются во внешнем потоке.
Хотя это работает нормально, я обнаружил, что нажатие на другие окна во время вызова WaitOne не имеет никакого эффекта. По сути, весь трафик сообщений Windows останавливается в ожидании возврата этого WaitHandle.
Я считаю, что мне нужно выполнить вызовы BeginStart и WaitOne в другом потоке; Мне все еще нужно, чтобы интерфейс дождался возвращения WaitOne, так как программа должна была умереть, и пользовательский интерфейс не должен отображаться, пока вызов WaitOne не завершится успешно (без тайм-аута). Просто нужно позволить другим программам обрабатывать свои сообщения Windows.
Как мне сделать эту работу? В WPF нет метода Application.DoEvents.
Tony
Edit:
Похоже, будет полезно, если я предоставлю еще немного информации.
Мое приложение WPF является пользовательским интерфейсом для этого продукта и составляет только половину всего продукта. Другая половина работает как служба Windows на том же ПК, и мы называем это back-end. То, что происходит в бэкэнде, неважно, за исключением того, что оно прослушивает соединения с ним с помощью XMPP.
Когда пользовательский интерфейс (или интерфейс) запускается, одна из вещей, которую он должен сделать, это установить связь с сервером с помощью XMPP. Обычно это занимает максимум пару секунд. Тем не менее, может быть что-то не так или сервер может быть недоступен, когда пользователь запускает интерфейс. Я не хочу, чтобы интерфейс ждал бесконечно; через разумный промежуток времени он должен истечь, вывести сообщение об ошибке и умереть.
Чтобы установить связь, есть модуль, который запускается как отдельный поток, который я запускаю. Я вызываю его метод BeginStart, который возвращает WaitHandle. Затем я подожду WaitHandle, передав интервал TimeSpan, установленный для моего периода ожидания. Вот фрагмент кода:
try {
WaitHandle handle = BackgroundProcess.BeginStart();
if ( !handle.WaitOne( Timeout ) ) {
// Something went wrong; Notify user here
return false;
}
// Make sure that the Background Process has started all of it's internal modules
bool allAreRunning;
Stopwatch timer = new Stopwatch();
timer.Reset(); timer.Start();
do {
allAreRunning = true;
foreach ( Module module in BackgroundProcess.Modules ) {
if ( module.State != Module.States.Running ) {
allAreRunning = false;
break;
}
}
if ( !allAreRunning ) {
// I hate this loop, but I can't think of a better way to do this
Thread.Sleep( 1000 );
}
} while ( !allAreRunning && timer.ElapsedMilliseconds <= Timeout.TotalMilliseconds );
timer.Stop();
if ( !allAreRunning ) {
// Something went wrong; Notify user here
return false;
}
// Other initialization done here
} catch ( Exception ex ) {
// Something went wrong; Notify user here
return false;
}
Чтобы проверить это, я запустил программу в отладчике, когда серверная часть не работала. Я могу нажать на любое открытое окно, переключиться на него и нормально с ним взаимодействовать. Что я не могу сделать, это нажать на рабочем столе. Вызов WaitHandle.WaitOne () возвращается очень быстро, поскольку он возвращается только после запуска фонового процесса и не ожидает установления соединения. Это цикл do-while, который выполняется большую часть времени ожидания.
Мне нужно переписать это, чтобы пользователь мог переключаться не только на открытие программ, но и на рабочий стол. Я просто не знаю, как заставить это работать.
Tony