view Implab/TaskController.cs @ 187:dd4a3590f9c6 ref20160224

Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler Any unhandled OperationCanceledException will cause the promise cancelation
author cin
date Tue, 19 Apr 2016 17:35:20 +0300
parents f75cfa58e3d4
children
line wrap: on
line source

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

namespace Implab
{
    /// <summary>
    /// This class allows to interact with asyncronuos task.
    /// </summary>
    /// <remarks>
    /// Members of this object are thread safe.
    /// </remarks>
    public class TaskController: IProgressNotifier, ITaskController
    {
        readonly object m_lock;
        string m_message;

        float m_current;
        float m_max;

        bool m_cancelled;

        public event EventHandler Cancelled;
        public event EventHandler<ValueEventArgs<string>> MessageUpdated;
        public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
        public event EventHandler<ProgressInitEventArgs> ProgressInit;

        public TaskController()
        {
            m_lock = new Object();
        }

        public string Message
        {
            get
            {
                lock (m_lock)
                    return m_message;
            }
            set
            {
                lock (m_lock)
                {
                    m_message = value;
                    OnMessageUpdated();
                }
            }
        }

        public float CurrentProgress
        {
            get
            {
                lock (m_lock)
                    return m_current;
            }
            set
            {
                lock (m_lock)
                {
                    var prev = m_current;
                    m_current = value;
                    if (m_current >= m_max)
                        m_current = m_max;
                    if (m_current != prev)
                        OnProgressUpdated();
                }
            }
        }

        public void InitProgress(float current, float max, string message)
        {
            if (max < 0)
                throw new ArgumentOutOfRangeException("max");
            if (current < 0 || current > max)
                throw new ArgumentOutOfRangeException("current");

            lock(m_lock) {
                m_current = current;
                m_max = max;
                m_message = message;
                OnProgressInit();
            }
        }

        public bool IsCancelled {
            get {
                lock (m_lock)
                    return m_cancelled;
            }
        }

        public void Cancel() {
            lock (m_lock) {
                if (!m_cancelled)
                    m_cancelled = true;
            }
        }

        public void Cancel(Exception reason) {
            lock (m_lock) {
                if (!m_cancelled)
                    m_cancelled = true;
            }
        }

        protected virtual void OnCancelled() {
            var temp = Cancelled;
            if (temp != null) {
                temp(this,new EventArgs());
            }
        }

        protected virtual void OnMessageUpdated()
        {
            var temp = MessageUpdated;
            if (temp != null)
            {
                temp(this, new ValueEventArgs<string>(m_message));
            }
        }

        protected virtual void OnProgressUpdated()
        {
            var temp = ProgressUpdated;
            if (temp != null)
            {
                temp(this,new ValueEventArgs<float>(m_current));
            }
        }

        protected virtual void OnProgressInit()
        {
            var temp = ProgressInit;
            if (temp != null)
            {
                temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
            }
        }
    }
}