Hi everyone,

I'm using WPF to make a nice UI for a completely automated system (to the point where there are no interactive controls what-so-ever) that downloads media from the net and learns from it. I've got a class that I've created which acts as an entry point to the entire system, as listed below. My question is, in the Startup method, should I wrap the entire method in a Thread and use Dispatchers to show/hide the window, or should I go about it a different way? The ATHENAProgram class has a single method, Run, which should be able to interact with the system window in a seperate thread (so that any long-running processes within the ATHENAProgram don't freeze the system).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ATHENA.Platform.UI;

namespace ATHENA.Platform.System
{
    public class ATHENASystem
    {
        /// <summary>
        /// Starts the specified program (this is the system's entry point).
        /// </summary>
        /// <param name="program">the program to run.</param>
        /// <param name="debugMode">true for debug mode.</param>
        public static void Startup(ATHENAProgram program, bool debugMode)
        {
            ATHENASystemWindow systemWindow = new ATHENASystemWindow();
            ATHENASystem system = new ATHENASystem(systemWindow, debugMode);
            systemWindow.Show();
            program.Run(system);
            systemWindow.Close();
        }

        // Fields.
        private ATHENASystemWindow m_systemWindow;
        private bool m_debugMode;

        /// <summary>
        /// Creates an instance of the system.
        /// </summary>
        /// <param name="systemWindow">the system window to interact with.</param>
        /// <param name="debugMode">true for debug mode.</param>
        private ATHENASystem(ATHENASystemWindow systemWindow, bool debugMode)
        {
            m_systemWindow = systemWindow;
            m_debugMode = debugMode;
        }

        /// <summary>
        /// Writes text to the console.
        /// </summary>
        /// <param name="text">the text to write.</param>
        /// <param name="bold">true for bold text.</param>
        /// <param name="italic">true for italic text.</param>
        /// <param name="underline">true for underlined text.</param>
        public void Write(string text, bool bold, bool italic, bool underline)
        {
            m_systemWindow.Console.Write(text, bold, italic, underline);
        }

        /// <summary>
        /// Writes text to the console if the system is in debug mode.
        /// </summary>
        /// <param name="text">the text to write.</param>
        /// <param name="bold">true for bold text.</param>
        /// <param name="italic">true for italic text.</param>
        /// <param name="underline">true for underlined text.</param>
        public void DebugWrite(string text, bool bold, bool italic, bool underline)
        {
            if (m_debugMode) Write(text, bold, italic, underline);
        }
    }
}

P.S. Write(...) and DebugWrite(...) are thread-safe (i.e. they update the UI with delegates).

Okay, I've now got the following code...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.Threading;
using ATHENA.Platform.UI;

namespace ATHENA.Platform.System
{
    public class ATHENASystem
    {
        // Delegates.
        private delegate void DShowWindow();
        private delegate void DCloseWindow();

        /// <summary>
        /// Starts the specified program (this is the system's entry point).
        /// </summary>
        /// <param name="program">the program to run.</param>
        /// <param name="debugMode">true for debug mode.</param>
        public static void Startup(ATHENAProgram program, bool debugMode)
        {
            ATHENASystemWindow systemWindow = new ATHENASystemWindow();
            Thread thread = new Thread(new ThreadStart(delegate
            {
                ATHENASystem system = new ATHENASystem(systemWindow, debugMode);
                system.ShowWindow();
                if (program != null) program.Run(system);
                system.CloseWindow();
            }));
            thread.Start();
        }

        // Fields.
        private ATHENASystemWindow m_systemWindow;
        private bool m_debugMode;

        /// <summary>
        /// Creates an instance of the system.
        /// </summary>
        /// <param name="systemWindow">the system window to interact with.</param>
        /// <param name="debugMode">true for debug mode.</param>
        private ATHENASystem(ATHENASystemWindow systemWindow, bool debugMode)
        {
            m_systemWindow = systemWindow;
            m_debugMode = debugMode;
        }

        /// <summary>
        /// Shows the window.
        /// </summary>
        private void ShowWindow()
        {
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Send,
                (DShowWindow)delegate
                {
                    m_systemWindow.Show();
                });
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        private void CloseWindow()
        {
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Send,
                (DCloseWindow)delegate
                {
                    m_systemWindow.Close();
                });
        }

        /// <summary>
        /// Writes text to the console.
        /// </summary>
        /// <param name="text">the text to write.</param>
        /// <param name="bold">true for bold text.</param>
        /// <param name="italic">true for italic text.</param>
        /// <param name="underline">true for underlined text.</param>
        public void Write(string text, bool bold, bool italic, bool underline)
        {
            m_systemWindow.Console.Write(text, bold, italic, underline);
        }

        /// <summary>
        /// Writes text to the console if the system is in debug mode.
        /// </summary>
        /// <param name="text">the text to write.</param>
        /// <param name="bold">true for bold text.</param>
        /// <param name="italic">true for italic text.</param>
        /// <param name="underline">true for underlined text.</param>
        public void DebugWrite(string text, bool bold, bool italic, bool underline)
        {
            if (m_debugMode) Write(text, bold, italic, underline);
        }
    }
}

This isn't working. My system seems to run the program, but it doesn't open the UI. Does anybody have any suggestions?

Perhaps I should rephrase my problem. What I need to do is show a Window in WPF, execute some code in a seperate thread that can update the UI asyncronously, and then close the window when the thread has finished executing. At the moment this is halting my progress, so it's pretty urgent that I find how to do this.

As the system gets more complex I'll need up to 9 more threads to run agents that will update a central database (e.g. one agent might be harvesting files from the internet, another might be processing images, another might be processing audio, and another might be extracting predicates from text files). After this, I'll probably need one more thread to get speech-based input from the user to allow him/her to converse with the system.

you could looka t backgroundworker class. It is a thread which can report its progress back to the calling thread.

you could looka t backgroundworker class. It is a thread which can report its progress back to the calling thread.

Thanks, that looks perfect for what I'm doing!!! :) I now have another question to ask; I'm planning on using a class derived from Application to show my window (which blocks the program from exiting until the main window is exited from, which is what I need); where abouts should I be starting the background thread in order to do this (e.g. OnStartup(...), OnLoadCompleted(...))? I'll also need to pass a couple of parameters to the background worker.

Thanks again for answering my previous question! :cool:

Thanks, that looks perfect for what I'm doing!!! :) I now have another question to ask; I'm planning on using a class derived from Application to show my window (which blocks the program from exiting until the main window is exited from, which is what I need); where abouts should I be starting the background thread in order to do this (e.g. OnStartup(...), OnLoadCompleted(...))? I'll also need to pass a couple of parameters to the background worker.

Thanks again for answering my previous question! :cool:

Nevermind, I sorted it! I added an event handler to the BackgroundWorker.Startup event. :twisted:

Glad you got this working :) Sorry i didnt reply. it was my birthday over the weekend so i was otherwise engaged :p

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.