I'm creating a wpf application which performs many tasks in the backgound, but still requires the UI to be responsive and to display the status of the various background tasks. It also has the option to not display the UI at all, in which case the status messages should be discarded without creating an instance of the main form at all.
What I've attempted is to remove
StartupUri="MainWindow.xaml"
from App.xaml. Then, in App.xaml.cs, I have
`
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.
}`
This shows the main form, if necessary, and starts all the background processes. This part works.
In order to send messages from the background to the UI, I've implemented a very basic messenger:
`
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);
}
}
}`
The main form implements the IMessageHandler interface, and adds itself to the Messenger as a handler when it starts up. Any process that needs to send a status to the main form just needs to call the Broadcast
method of the messenger.
The problem I'm having, is that the messages are not being shown on the form until the background processes complete, and the UI is locked up until then as well.
The code in the UI which handles receiving messages is as follows:
`
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);
}
}`
Why are my background processes freezing my UI? What can I do to prevent it? And why is my UI not updating with the status messages?