ui/wpf/UIcore/Application.cs

Sun, 15 Jan 2017 15:08:07 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 15 Jan 2017 15:08:07 +0100
changeset 132
a24465cc7262
parent 89
9a7e4a335b2b
child 135
b9dc9cdfa23a
permissions
-rw-r--r--

fixes VS settings

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace UI
{  
    public class Application
    {
        private static Application instance;

        private System.Windows.Application application;

        private Thread thread;
        private Queue<Action> queue = new Queue<Action>();
        private object sync = new object();
        private object result = new object();
        private Boolean main = false;

        public String Name;
        public List<Window> Windows = new List<Window>();
        public ApplicationMenu Menu = new ApplicationMenu();
        public MainToolBar ToolBar = new MainToolBar();
        
        private Application() : base()
        {
            thread = new Thread(() => Run());
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        public static Application GetInstance()
        {
            if (instance == null)
            {
                instance = new Application();
                GC.KeepAlive(instance);
            }
            return instance;
        }

        public Thread Start()
        {
            lock(sync)
            {
                queue.Enqueue(() => RunApplication());
                Monitor.Pulse(sync);
            }
            return thread;
        }

        private void RunApplication()
        {
            application = new System.Windows.Application();
            main = true;
            application.Run();
        }

        public void Run()
        {
            lock(sync)
            {
                for (;;)
                {
                    Monitor.Wait(sync);
                    Action action = queue.Dequeue();
                    action.Invoke();
                    lock (result)
                    {
                        Monitor.Pulse(result);
                    }
                    if (main)
                    {
                        // end loop after shutdown
                        break;
                    }
                }
            }
        }

        public T Exec<T>(Func<T> func)
        {
            ResultExec<T> e = new ResultExec<T>();
            e.Func = func;

            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                e.Exec();
                return e.Result;
            }
            else
            {
                lock (sync)
                {
                    queue.Enqueue(() => e.Exec());
                    Monitor.Pulse(sync);
                }
                lock (result)
                {
                    Monitor.Wait(result);
                }

                return e.Result;
            }
        }

        public void Exec(Action action)
        {
            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                action.Invoke();
            }
            else
            {
                lock (sync)
                {
                    queue.Enqueue(action);
                    Monitor.Pulse(sync);
                }
                lock (result)
                {
                    Monitor.Wait(result);
                }
            }
        }

        public void AddWindow(Window window)
        {
            Windows.Add(window);
        }

        public void RemoveWindow(Window window)
        {
            Windows.Remove(window);
            if (Windows.Count == 0)
            {
                application.Shutdown();
            }
        }
    }

    public class ResultExec<T>
    {
        public T Result;
        public Func<T> Func;

        public void Exec()
        {
            Result = Func.Invoke();
        }
    }

    public class VoidExec
    {
        public Action Action;

        public void Exec()
        {
            Action.Invoke();
        }
    }
}

mercurial