Я создаю приложение wpf, которое выполняет много задач в фоновом режиме, но все же требует, чтобы пользовательский интерфейс реагировал и отображал состояние различных фоновых задач. Он также имеет возможность вообще не отображать пользовательский интерфейс, и в этом случае сообщения о состоянии должны быть отброшены без создания экземпляра основной формы.
Я пытался удалить
StartupUri="MainWindow.xaml"
от App.xaml. Затем в App.xaml.cs у меня есть
`
public App()
{
Startup += new StartupEventHandler(App_Startup);
}
void App_Startup(object sender, StartupEventArgs e)
{
// Code which loads application settings is here
if (pf.ShowUI)
{
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
}
// The background processes will begin here.
}`
Показывает основную форму, если необходимо, и запускает все фоновые процессы. Эта часть работает.
Чтобы отправлять сообщения из фона в пользовательский интерфейс, я реализовал очень простой мессенджер:
`
internal interface IMessageHandler
{
void ReceiveMessage(string message);
}
internal class Messenger
{
private static List<IMessageHandler> _handlers;
internal static void AddHandler(IMessageHandler handler)
{
_handlers.Add(handler);
}
internal static void RemoveHandler(IMessageHandler handler)
{
try
{
_handlers.Remove(handler);
}
catch (Exception ex) {}
}
internal static void Broadcast (string message)
{
foreach (IMessageHandler handler in _handlers)
{
handler.ReceiveMessage(message);
}
}
}`
Основная форма реализует интерфейс IMessageHandler и добавляет себя в Messenger в качестве обработчика при запуске. Любой процесс, которому нужно отправить статус в основную форму, просто должен вызвать метод Broadcast
мессенджера.
Проблема, с которой я столкнулся, заключается в том, что сообщения не отображаются в форме до тех пор, пока не завершатся фоновые процессы, и пользовательский интерфейс также будет заблокирован до тех пор.
Код в пользовательском интерфейсе, который обрабатывает получение сообщений, выглядит следующим образом:
`
public void ReceiveMessage(string message)
{
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<string>(AddText),
message);
}
private void AddText(string text)
{
Label myLabel = new Label();
myLabel.Content = text;
stackPanel1.Children.Add(myLabel);
if (stackPanel1.Children.Count > 5)
{
stackPanel1.Children.RemoveAt(0);
}
}`
Почему мои фоновые процессы замораживают мой интерфейс? Что я могу сделать, чтобы предотвратить это? И почему мой интерфейс не обновляется сообщениями о состоянии?