Wednesday, 21 January 2015

Custom DispatchQueue with a Worker thread

public class DispatchQueue
    {
        Queue<Action> queue = new Queue<Action> ();
        static object key = new object ();
        SingleThreadDispatcher dispatcher;

        public DispatchQueue(SingleThreadDispatcher dispatcher) {
            this.dispatcher = dispatcher;
        }

        public void QueueWork(Action work){
            lock (key) {
                queue.Enqueue (work);
            }

            if (this.dispatcher.Executed) {
                this.dispatcher.Dispatch (this.Dequeue (), SynchronizationContext.Current, this.Callback);
            }
        }

        private Action Dequeue(){
            lock (key) {
                if (queue.Count <= 0) {
                    return null;
                }

                return queue.Dequeue ();
            }
        }

        private void Callback(object state) {
            var work = this.Dequeue ();

            if (work == null) return;

            this.dispatcher.Dispatch (work, SynchronizationContext.Current, this.Callback);
        }
    }


public class SingleThreadDispatcher
    {
        Task task = null;

        public void Dispatch(Action work, SynchronizationContext context, Action<object> callback) {
            if (work == null || context == null || callback == null || !this.Executed) {
                return;
            }

            Action safeWork = () => this.Execute (work);
            this.task = new Task (safeWork);
            this.task.ContinueWith ((result) => {
                context.Post(new SendOrPostCallback(callback), null);
            });

            this.task.Start ();
        }

        public bool Executed {
            get{
                return (task == null) || (task != null && task.IsCompleted);
            }
        }

        private void Execute(Action work)
        {
            try {
                work();
            }
            catch(Exception e) {
                //
            }
        }
    }