view Implab.Fx/PromiseHelpers.cs @ 72:d67b95eddaf4 v2

promises refactoring
author cin
date Thu, 04 Sep 2014 18:47:12 +0400
parents 381095ad0a69
children c761fc982e1d
line wrap: on
line source

using System;
using System.Windows.Forms;
using System.Threading;

namespace Implab.Fx
{
    public static class PromiseHelpers
    {
        /// <summary>
        /// Перенаправляет обработку обещания в поток указанного элемента управления.
        /// </summary>
        /// <typeparam name="T">Тип результата обещания</typeparam>
        /// <param name="that">Исходное обещание</param>
        /// <param name="ctl">Элемент управления</param>
        /// <returns>Новое обещание, обработчики которого будут выполнены в потоке элемента управления.</returns>
        /// <exception cref="ArgumentNullException">Параметр не может быть <c>null</c>.</exception>
        /// <example>
        /// client
        ///     .Get("description.txt") // returns a promise
        ///     .DirectToControl(m_ctl) // handle the promise in the thread of the control
        ///     .Then(
        ///         description => m_ctl.Text = description // now it's safe
        ///     )
        /// </example>
        public static Promise<T> DispatchToControl<T>(this Promise<T> that, Control ctl)
        {
            if (that == null)
                throw new ArgumentNullException("that");
            if (ctl == null)
                throw new ArgumentNullException("ctl");

            var directed = new ControlBoundPromise<T>(ctl,that,true);

            that.Then(
                directed.Resolve,
                err =>
                {
                    directed.Reject(err);
                    return default(T);
                }
            );

            return directed;
        }

        /// <summary>
        /// Направляет обработку обещания в текущий поток, если у него существует контекст синхронизации.
        /// </summary>
        /// <typeparam name="T">Тип результата обещания.</typeparam>
        /// <param name="that">Обещание которое нужно обработать в текущем потоке.</param>
        /// <returns>Перенаправленное обещание.</returns>
        public static Promise<T> DispatchToCurrentThread<T>(this Promise<T> that)
        {
            var sync = SynchronizationContext.Current;
            if (sync == null)
                throw new InvalidOperationException("The current thread doesn't have a syncronization context");
            return DispatchToSyncContext(that, sync);
        }

        /// <summary>
        /// Направляет обработку обещания в указанный контекст синхронизации.
        /// </summary>
        /// <typeparam name="T">Тип результата обещания.</typeparam>
        /// <param name="that">Обещание, которое требуется обработать в указанном контексте синхронизации.</param>
        /// <param name="sync">Контекст синхронизации в который будет направлено обещание.</param>
        /// <returns>Новое обещание, которое будет обрабатываться в указанном контексте.</returns>
        public static Promise<T> DispatchToSyncContext<T>(this Promise<T> that, SynchronizationContext sync)
        {
            if (that == null)
                throw new ArgumentNullException("that");
            if (sync == null)
                throw new ArgumentNullException("sync");

            var d = new Promise<T>();

            that.Then(
                res => sync.Post(state => d.Resolve(res), null),
                err => {
                    sync.Post(state => d.Reject(err), null);
                    return default(T);
                }
            );

            return d;
        }
    }
}