diff --git a/Implab.Fx.Test/Implab.Fx.Test.csproj b/Implab.Fx.Test/Implab.Fx.Test.csproj
deleted file mode 100644
--- a/Implab.Fx.Test/Implab.Fx.Test.csproj
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-  
-    Debug
-    AnyCPU
-    8.0.30703
-    2.0
-    {2F31E405-E267-4195-A05D-574093C21209}
-    Library
-    Properties
-    Implab.Fx.Test
-    Implab.Fx.Test
-    v4.5
-    512
-    {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
-    
-  
-  
-    true
-    full
-    false
-    bin\Debug\
-    DEBUG;TRACE
-    prompt
-    4
-    false
-  
-  
-    pdbonly
-    true
-    bin\Release\
-    TRACE
-    prompt
-    4
-    false
-  
-  
-    true
-    full
-    false
-    bin\Debug\
-    DEBUG;TRACE
-    prompt
-    4
-    false
-  
-  
-    pdbonly
-    true
-    bin\Release\
-    TRACE
-    prompt
-    4
-    false
-  
-  
-    
-    
-    
-      3.5
-    
-    
-    
-    
-    
-    
-  
-  
-    
-    
-    
-      Form
-    
-    
-      MainForm.cs
-    
-    
-      Form
-    
-    
-      OverlayForm.cs
-    
-    
-  
-  
-    
-      MainForm.cs
-      
-      
-    
-    
-      OverlayForm.cs
-      
-      
-    
-  
-  
-    
-      {06E706F8-6881-43EB-927E-FFC503AF6ABC}
-      Implab.Fx
-    
-    
-      {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
-      Implab
-    
-  
-  
-  
-
\ No newline at end of file
diff --git a/Implab.Fx.Test/Implab.Fx.Test.mono.csproj b/Implab.Fx.Test/Implab.Fx.Test.mono.csproj
deleted file mode 100644
--- a/Implab.Fx.Test/Implab.Fx.Test.mono.csproj
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-  
-    Debug
-    AnyCPU
-    8.0.30703
-    2.0
-    {2BD05F84-E067-4B87-9477-FDC2676A21C6}
-    Library
-    Implab.Fx.Test
-    Implab.Fx.Test
-    v4.5
-  
-  
-    true
-    full
-    false
-    bin\Debug
-    DEBUG;MONO
-    prompt
-    4
-    false
-  
-  
-    true
-    bin\Release
-    prompt
-    4
-    false
-    MONO
-  
-  
-    true
-    full
-    false
-    bin\Debug
-    DEBUG;TRACE;NET_4_5;MONO
-    prompt
-    4
-    false
-  
-  
-    true
-    bin\Release
-    NET_4_5;MONO
-    prompt
-    4
-    false
-  
-  
-    
-    
-    
-    
-    
-  
-  
-  
-    
-      {06E706F8-6881-43EB-927E-FFC503AF6ABC}
-      Implab.Fx
-    
-    
-      {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
-      Implab
-    
-  
-  
-    
-    
-    
-    
-    
-    
-  
-  
-    
-    
-  
-
\ No newline at end of file
diff --git a/Implab.Fx.Test/OverlayTest.cs b/Implab.Fx.Test/OverlayTest.cs
deleted file mode 100644
--- a/Implab.Fx.Test/OverlayTest.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System.Windows.Forms;
-using Implab.Fx.Test.Sample;
-using Implab.Fx;
-
-#if MONO
-
-using NUnit.Framework;
-using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
-using TestMethod = NUnit.Framework.TestAttribute;
-
-#else
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-#endif
-
-namespace Implab.Fx.Test
-{
-    [TestClass]
-    public class OverlayTest
-    {
-        [TestMethod]
-        public void TestMethod1()
-        {
-            var mainForm = new MainForm();
-            
-            mainForm.ButtonEvent += (sender, args) =>
-            {
-                var overlay = new OverlayForm();
-                mainForm.OverlayFadeIn(overlay).On(
-                    o => o.ButtonEvent += (s2, args2) => o.CloseFadeOut()
-                );
-            };
-            
-            Application.Run(mainForm);
-        }
-    }
-}
diff --git a/Implab.Fx.Test/Properties/AssemblyInfo.cs b/Implab.Fx.Test/Properties/AssemblyInfo.cs
deleted file mode 100644
--- a/Implab.Fx.Test/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Implab.Fx.Test")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Implab.Fx.Test")]
-[assembly: AssemblyCopyright("Copyright ©  2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("ac9cc552-177e-4b6d-923c-763dc6f87dd6")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Implab.Fx.Test/Sample/MainForm.Designer.cs b/Implab.Fx.Test/Sample/MainForm.Designer.cs
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/MainForm.Designer.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-namespace Implab.Fx.Test.Sample
-{
-    partial class MainForm
-    {
-        /// 
-        /// Required designer variable.
-        /// 
-        private System.ComponentModel.IContainer components = null;
-
-        /// 
-        /// Clean up any resources being used.
-        /// 
-        /// true if managed resources should be disposed; otherwise, false.
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Windows Form Designer generated code
-
-        /// 
-        /// Required method for Designer support - do not modify
-        /// the contents of this method with the code editor.
-        /// 
-        private void InitializeComponent()
-        {
-            this.button1 = new System.Windows.Forms.Button();
-            this.comboBox1 = new System.Windows.Forms.ComboBox();
-            this.listBox1 = new System.Windows.Forms.ListBox();
-            this.SuspendLayout();
-            // 
-            // button1
-            // 
-            this.button1.Location = new System.Drawing.Point(138, 12);
-            this.button1.Name = "button1";
-            this.button1.Size = new System.Drawing.Size(75, 23);
-            this.button1.TabIndex = 0;
-            this.button1.Text = "button1";
-            this.button1.UseVisualStyleBackColor = true;
-            this.button1.Click += new System.EventHandler(this.button1_Click);
-            // 
-            // comboBox1
-            // 
-            this.comboBox1.FormattingEnabled = true;
-            this.comboBox1.Location = new System.Drawing.Point(138, 41);
-            this.comboBox1.Name = "comboBox1";
-            this.comboBox1.Size = new System.Drawing.Size(121, 21);
-            this.comboBox1.TabIndex = 1;
-            // 
-            // listBox1
-            // 
-            this.listBox1.FormattingEnabled = true;
-            this.listBox1.Location = new System.Drawing.Point(12, 12);
-            this.listBox1.Name = "listBox1";
-            this.listBox1.Size = new System.Drawing.Size(120, 95);
-            this.listBox1.TabIndex = 2;
-            // 
-            // MainForm
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(284, 262);
-            this.Controls.Add(this.listBox1);
-            this.Controls.Add(this.comboBox1);
-            this.Controls.Add(this.button1);
-            this.Name = "MainForm";
-            this.Text = "MainForm";
-            this.ResumeLayout(false);
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.Button button1;
-        private System.Windows.Forms.ComboBox comboBox1;
-        private System.Windows.Forms.ListBox listBox1;
-    }
-}
\ No newline at end of file
diff --git a/Implab.Fx.Test/Sample/MainForm.cs b/Implab.Fx.Test/Sample/MainForm.cs
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/MainForm.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-namespace Implab.Fx.Test.Sample
-{
-    public partial class MainForm : Form
-    {
-        public event EventHandler ButtonEvent;
-
-        public MainForm()
-        {
-            InitializeComponent();
-        }
-
-        private void button1_Click(object sender, EventArgs e)
-        {
-            EventHandler temp = ButtonEvent;
-            if (temp != null)
-            {
-                temp(this,new EventArgs());
-            }
-        }
-    }
-}
diff --git a/Implab.Fx.Test/Sample/MainForm.resx b/Implab.Fx.Test/Sample/MainForm.resx
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/MainForm.resx
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-  
-  
-    
-    
-      
-        
-          
-            
-              
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-              
-            
-          
-          
-            
-              
-                
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-                
-              
-              
-            
-          
-        
-      
-    
-  
-  
-    text/microsoft-resx
-  
-  
-    2.0
-  
-  
-    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-  
-    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-
\ No newline at end of file
diff --git a/Implab.Fx.Test/Sample/OverlayForm.Designer.cs b/Implab.Fx.Test/Sample/OverlayForm.Designer.cs
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/OverlayForm.Designer.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-namespace Implab.Fx.Test.Sample
-{
-    partial class OverlayForm
-    {
-        /// 
-        /// Required designer variable.
-        /// 
-        private System.ComponentModel.IContainer components = null;
-
-        /// 
-        /// Clean up any resources being used.
-        /// 
-        /// true if managed resources should be disposed; otherwise, false.
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Windows Form Designer generated code
-
-        /// 
-        /// Required method for Designer support - do not modify
-        /// the contents of this method with the code editor.
-        /// 
-        private void InitializeComponent()
-        {
-            this.button1 = new System.Windows.Forms.Button();
-            this.checkBox1 = new System.Windows.Forms.CheckBox();
-            this.label1 = new System.Windows.Forms.Label();
-            this.progressBar1 = new System.Windows.Forms.ProgressBar();
-            this.SuspendLayout();
-            // 
-            // button1
-            // 
-            this.button1.Location = new System.Drawing.Point(12, 12);
-            this.button1.Name = "button1";
-            this.button1.Size = new System.Drawing.Size(75, 23);
-            this.button1.TabIndex = 0;
-            this.button1.Text = "button1";
-            this.button1.UseVisualStyleBackColor = true;
-            this.button1.Click += new System.EventHandler(this.button1_Click);
-            // 
-            // checkBox1
-            // 
-            this.checkBox1.AutoSize = true;
-            this.checkBox1.Location = new System.Drawing.Point(12, 88);
-            this.checkBox1.Name = "checkBox1";
-            this.checkBox1.Size = new System.Drawing.Size(80, 17);
-            this.checkBox1.TabIndex = 1;
-            this.checkBox1.Text = "checkBox1";
-            this.checkBox1.UseVisualStyleBackColor = true;
-            // 
-            // label1
-            // 
-            this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(13, 42);
-            this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(35, 13);
-            this.label1.TabIndex = 2;
-            this.label1.Text = "label1";
-            // 
-            // progressBar1
-            // 
-            this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.progressBar1.Location = new System.Drawing.Point(12, 59);
-            this.progressBar1.Name = "progressBar1";
-            this.progressBar1.Size = new System.Drawing.Size(260, 23);
-            this.progressBar1.TabIndex = 3;
-            // 
-            // OverlayForm
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(284, 262);
-            this.Controls.Add(this.progressBar1);
-            this.Controls.Add(this.label1);
-            this.Controls.Add(this.checkBox1);
-            this.Controls.Add(this.button1);
-            this.Name = "OverlayForm";
-            this.Text = "OverlayForm";
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.Button button1;
-        private System.Windows.Forms.CheckBox checkBox1;
-        private System.Windows.Forms.Label label1;
-        private System.Windows.Forms.ProgressBar progressBar1;
-    }
-}
\ No newline at end of file
diff --git a/Implab.Fx.Test/Sample/OverlayForm.cs b/Implab.Fx.Test/Sample/OverlayForm.cs
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/OverlayForm.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-namespace Implab.Fx.Test.Sample
-{
-    public partial class OverlayForm : Form
-    {
-        public event EventHandler ButtonEvent;
-
-        public OverlayForm()
-        {
-            InitializeComponent();
-        }
-
-        private void button1_Click(object sender, EventArgs e)
-        {
-            EventHandler temp = ButtonEvent;
-            if (temp != null)
-            {
-                temp(this,new EventArgs());
-            }
-        }
-    }
-}
diff --git a/Implab.Fx.Test/Sample/OverlayForm.resx b/Implab.Fx.Test/Sample/OverlayForm.resx
deleted file mode 100644
--- a/Implab.Fx.Test/Sample/OverlayForm.resx
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-  
-  
-    
-    
-      
-        
-          
-            
-              
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-              
-            
-          
-          
-            
-              
-                
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-                
-              
-              
-            
-          
-        
-      
-    
-  
-  
-    text/microsoft-resx
-  
-  
-    2.0
-  
-  
-    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-  
-    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-
\ No newline at end of file
diff --git a/Implab.Fx.Test/StaApartmentTests.cs b/Implab.Fx.Test/StaApartmentTests.cs
deleted file mode 100644
--- a/Implab.Fx.Test/StaApartmentTests.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Reflection;
-using System.Threading;
-using Implab.Parallels;
-using Implab.Components;
-
-#if MONO
-
-using NUnit.Framework;
-using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
-using TestMethodAttribute = NUnit.Framework.TestAttribute;
-using AssertFailedException = NUnit.Framework.AssertionException;
-#else
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-#endif
-namespace Implab.Fx.Test {
-    [TestClass]
-    public class StaApartmentTests {
-        [TestMethod]
-        public void CreateDestroyApartment() {
-            var apartment = new StaApartment();
-            try {
-                Assert.IsNotNull(apartment.SyncContext);
-                Assert.Fail();
-            } catch (InvalidOperationException) {
-                // OK
-            }
-
-            apartment.Start().Join();
-            Assert.AreEqual(apartment.State, ExecutionState.Running);
-
-            Assert.IsNotNull(apartment.SyncContext);
-            apartment.Stop().Join();
-            
-            Assert.IsTrue(apartment.State == ExecutionState.Disposed);
-        }
-
-        [TestMethod]
-        public void InvokeInApartment() {
-            var apartment = new StaApartment();
-
-            apartment.Start().Join();
-
-            var apType = apartment.Invoke(() => { return Thread.CurrentThread.GetApartmentState(); }).Join();
-            Assert.AreEqual(apType, ApartmentState.STA);
-
-            apartment.Stop().Join();
-        }
-    }
-}
diff --git a/Implab.Fx/Animation.cs b/Implab.Fx/Animation.cs
deleted file mode 100644
--- a/Implab.Fx/Animation.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Timers;
-using System.ComponentModel;
-using System.Diagnostics;
-
-namespace Implab.Fx
-{
-    public delegate void AnimationStep(T target, int elapsed, int duration);
-
-    public class Animation where TArg: class
-    {
-        int m_duration;
-        int m_delay;
-        int m_elapsed;
-        int m_prevTicks;
-        TArg m_arg;
-        ISynchronizeInvoke m_syncronizationObject;
-
-        public event AnimationStep Step;
-
-        Promise m_promise;
-
-        public Animation(TArg target, int duration, int delay)
-        {
-            if (duration <= 0)
-                throw new ArgumentOutOfRangeException("duration");
-            if (delay <= 0)
-                throw new ArgumentOutOfRangeException("delay");
-
-            m_arg = target;
-            m_syncronizationObject = target as ISynchronizeInvoke;
-            m_duration = duration;
-            m_delay = delay;
-            m_promise = new Promise();
-        }
-
-        public Animation(TArg target)
-            : this(target, 500, 30)
-        {
-        }
-
-        public TArg Traget
-        {
-            get { return m_arg; }
-        }
-
-        public Promise Play()
-        {
-            var timer = new Timer(m_delay);
-            
-            timer.AutoReset = false;
-            timer.SynchronizingObject = m_syncronizationObject;
-            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
-
-            m_prevTicks = Environment.TickCount;
-
-            timer.Start();
-
-            return m_promise;
-        }
-
-        void timer_Elapsed(object sender, ElapsedEventArgs args)
-        {
-            var timer = sender as Timer;
-
-            var dt = Environment.TickCount - m_prevTicks;
-            m_prevTicks = Environment.TickCount;
-
-            m_elapsed += dt;
-
-            if (m_elapsed > m_duration)
-                m_elapsed = m_duration;
-
-            try
-            {
-                var handler = Step;
-                if (handler != null)
-                    handler(m_arg, m_elapsed, m_duration);
-            }
-            catch (Exception e)
-            {
-                Trace.TraceError(e.ToString());
-            }
-
-            if (m_elapsed < m_duration)
-                timer.Start();
-            else
-            {
-                timer.Dispose();
-                m_promise.Resolve(m_arg);
-            }
-        }
-    }
-}
diff --git a/Implab.Fx/AnimationHelpers.cs b/Implab.Fx/AnimationHelpers.cs
deleted file mode 100644
--- a/Implab.Fx/AnimationHelpers.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-using System.Diagnostics;
-
-namespace Implab.Fx
-{
-    public static class AnimationHelpers
-    {
-        public static Animation AnimateProperty(this Animation animation, Action setter, Func getter, TVal newValue, Func fx) where TTarget : class
-        {
-            if (animation == null)
-                throw new ArgumentNullException("animation");
-
-            TVal oldValue = getter(animation.Traget);
-
-            animation.Step += (target, elaped, duration) =>
-            {
-                var value = fx(oldValue, newValue, elaped, duration);
-                setter(target, value);
-            };
-
-            return animation;
-        }
-
-        public static Animation AnimateTransparency(this T ctl, float newValue) where T : Form
-        {
-            var anim = new Animation(ctl);
-
-            anim.AnimateProperty(
-                (target, value) => target.Opacity = value,
-                target => target.Opacity,
-                newValue,
-                (ov, nv, el, du) => ov + ((float)el / du) * (nv - ov)
-            );
-            return anim;
-        }
-
-        public static IPromise CloseFadeOut(this T ctl) where T : Form
-        {
-            var anim = ctl.AnimateTransparency(0);
-
-            return anim
-                .Play()
-                .DispatchToControl(ctl)
-                .Then(frm => {
-                    frm.Close();
-                    return frm;
-                });
-        }
-
-        public static IPromise OverlayFadeIn(this Form that, T overlay) where T : Form
-        {
-            if (that == null)
-                throw new ArgumentNullException("that");
-            if (overlay == null)
-                throw new ArgumentNullException("overlay");
-
-            // setup overlay
-            overlay.Opacity = 0;
-            overlay.FormBorderStyle = FormBorderStyle.None;
-            overlay.ShowInTaskbar = false;
-
-            that.AddOwnedForm(overlay);
-
-            EventHandler handler = (object sender, EventArgs args) =>
-            {
-                overlay.Bounds = that.RectangleToScreen(that.ClientRectangle);
-            };
-
-            // attach handlers
-            that.Move += handler;
-            that.Resize += handler;
-            that.Shown += handler;
-
-            // remove handlers to release overlay
-            overlay.FormClosed += (sender, args) =>
-            {
-                that.Move -= handler;
-                that.Resize -= handler;
-                that.Shown -= handler;
-            };
-
-            overlay.Show(that);
-            overlay.Bounds = that.RectangleToScreen(that.ClientRectangle);
-
-            return overlay
-                .AnimateTransparency(1)
-                .Play()
-                .DispatchToControl(overlay);
-        }
-    }
-}
diff --git a/Implab.Fx/ControlBoundPromise.cs b/Implab.Fx/ControlBoundPromise.cs
deleted file mode 100644
--- a/Implab.Fx/ControlBoundPromise.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Windows.Forms;
-using System;
-
-
-namespace Implab.Fx {
-    public class ControlBoundPromise : Promise {
-        readonly Control m_target;
-
-        public ControlBoundPromise(Control target) {
-            Safe.ArgumentNotNull(target, "target");
-
-            m_target = target;
-        }
-
-        protected override void SignalHandler(HandlerDescriptor handler, int signal) {
-            if (m_target.InvokeRequired)
-                m_target.BeginInvoke(new Action.HandlerDescriptor, int>(base.SignalHandler), handler, signal);
-            else
-                base.SignalHandler(handler, signal);
-        }
-    }
-}
-
diff --git a/Implab.Fx/Implab.Fx.csproj b/Implab.Fx/Implab.Fx.csproj
deleted file mode 100644
--- a/Implab.Fx/Implab.Fx.csproj
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-  
-    Debug
-    AnyCPU
-    8.0.30703
-    2.0
-    {06E706F8-6881-43EB-927E-FFC503AF6ABC}
-    Library
-    Properties
-    Implab.Fx
-    Implab.Fx
-    v4.5
-    512
-    0.2
-    
-  
-  
-    true
-    full
-    false
-    bin\Debug\
-    DEBUG;TRACE
-    prompt
-    4
-    false
-  
-  
-    pdbonly
-    true
-    bin\Release\
-    TRACE
-    prompt
-    4
-    false
-  
-  
-    true
-    full
-    false
-    bin\Debug\
-    DEBUG;TRACE
-    prompt
-    4
-    false
-  
-  
-    pdbonly
-    true
-    bin\Release\
-    TRACE
-    prompt
-    4
-    false
-  
-  
-    
-    
-    
-    
-    
-    
-    
-    
-    
-  
-  
-    
-    
-    
-    
-    
-    
-  
-  
-    
-      {F550F1F8-8746-4AD0-9614-855F4C4B7F05}
-      Implab
-    
-  
-  
-  
-
\ No newline at end of file
diff --git a/Implab.Fx/PromiseHelpers.cs b/Implab.Fx/PromiseHelpers.cs
deleted file mode 100644
--- a/Implab.Fx/PromiseHelpers.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Windows.Forms;
-using System.Threading;
-
-namespace Implab.Fx
-{
-    public static class PromiseHelpers
-    {
-        /// 
-        /// Перенаправляет обработку обещания в поток указанного элемента управления.
-        /// 
-        /// Тип результата обещания
-        /// Исходное обещание
-        /// Элемент управления
-        /// Новое обещание, обработчики которого будут выполнены в потоке элемента управления.
-        /// Параметр не может быть null.
-        /// 
-        /// client
-        ///     .Get("description.txt") // returns a promise
-        ///     .DispatchToControl(m_ctl) // handle the promise in the thread of the control
-        ///     .Then(
-        ///         description => m_ctl.Text = description // now it's safe
-        ///     )
-        /// 
-        public static IPromise DispatchToControl(this IPromise that, Control ctl)
-        {
-            Safe.ArgumentNotNull(that, "that");
-            Safe.ArgumentNotNull(ctl, "ctl");
-
-            var directed = new ControlBoundPromise(ctl);
-
-            directed.On(that.Cancel, PromiseEventType.Cancelled);
-
-            that.On(
-                directed.Resolve,
-                directed.Reject,
-                directed.Cancel
-            );
-
-            return directed;
-        }
-    }
-}
diff --git a/Implab.Fx/Properties/AssemblyInfo.cs b/Implab.Fx/Properties/AssemblyInfo.cs
deleted file mode 100644
--- a/Implab.Fx/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Implab.Fx")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Implab.Fx")]
-[assembly: AssemblyCopyright("Copyright ©  2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("d239c29f-98e2-4942-9569-554a8511d07b")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.*")]
diff --git a/Implab.Fx/StaApartment.cs b/Implab.Fx/StaApartment.cs
deleted file mode 100644
--- a/Implab.Fx/StaApartment.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using Implab.Components;
-using Implab.Diagnostics;
-using Implab.Parallels;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace Implab.Fx {
-    public class StaApartment : RunnableComponent {
-        readonly Thread m_worker;
-        SynchronizationContext m_syncContext;
-        SyncContextPromise m_enterPromise;
-
-        readonly Promise m_threadStarted;
-        readonly Promise m_threadTerminated;
-
-        public StaApartment() : base(true) {
-            m_threadStarted = new Promise();
-            m_threadTerminated = new Promise();
-
-            m_worker = new Thread(WorkerEntry);
-            m_worker.SetApartmentState(ApartmentState.STA);
-            m_worker.IsBackground = true;
-            m_worker.Name = "STA managed aparment";
-        }
-
-        public SynchronizationContext SyncContext {
-            get {
-                if (m_syncContext == null)
-                    throw new InvalidOperationException();
-                return m_syncContext;
-            }
-        }
-
-        /// 
-        /// Returns the promise which will dispatch all handlers inside the apartment using it's 
-        /// 
-        /// 
-        /// Current implementation is optimized and will lost aync operation stack
-        /// 
-        /// The promise
-        public IPromise Enter() {
-            if (m_enterPromise == null)
-                throw new InvalidOperationException();
-            return m_enterPromise;
-        }
-
-        public IPromise Invoke(Action action) {
-            Safe.ArgumentNotNull(action, "action");
-
-            if (m_syncContext == null)
-                throw new InvalidOperationException();
-            var p = new Promise();
-            var lop = TraceContext.Instance.CurrentOperation;
-
-            m_syncContext.Post(x => {
-                TraceContext.Instance.EnterLogicalOperation(lop, false);
-                try {
-                    if (p.CancelOperationIfRequested())
-                        return;
-
-                    action(p);
-                    p.Resolve();
-                } catch (Exception e) {
-                    p.Reject(e);
-                } finally {
-                    TraceContext.Instance.Leave();
-                }
-            }, null);
-
-            return p;
-        }
-
-        public IPromise Invoke(Func action) {
-            Safe.ArgumentNotNull(action, "action");
-
-            if (m_syncContext == null)
-                throw new InvalidOperationException();
-            var p = new Promise();
-            var lop = TraceContext.Instance.CurrentOperation;
-
-            m_syncContext.Post(x => {
-                TraceContext.Instance.EnterLogicalOperation(lop, false);
-                try {
-                    if (p.CancelOperationIfRequested())
-                        return;
-                    p.Resolve(action(p));
-                } catch (Exception e) {
-                    p.Reject(e);
-                } finally {
-                    TraceContext.Instance.Leave();
-                }
-            }, null);
-
-            return p;
-        }
-
-        public IPromise Invoke(Action action) {
-            Safe.ArgumentNotNull(action, "action");
-
-            if (m_syncContext == null)
-                throw new InvalidOperationException();
-            var p = new Promise();
-            var lop = TraceContext.Instance.CurrentOperation;
-
-            m_syncContext.Post(x => {
-                TraceContext.Instance.EnterLogicalOperation(lop, false);
-                try {
-                    if (p.CancelOperationIfRequested())
-                        return;
-                    action();
-                    p.Resolve();
-                } catch (Exception e) {
-                    p.Reject(e);
-                } finally {
-                    TraceContext.Instance.Leave();
-                }
-            }, null);
-
-            return p;
-        }
-
-        public IPromise Invoke(Func action) {
-            Safe.ArgumentNotNull(action, "action");
-
-            if (m_syncContext == null)
-                throw new InvalidOperationException();
-            var p = new Promise();
-            var lop = TraceContext.Instance.CurrentOperation;
-
-            m_syncContext.Post(x => {
-                TraceContext.Instance.EnterLogicalOperation(lop, false);
-                try {
-                    if (p.CancelOperationIfRequested())
-                        return;
-                    p.Resolve(action());
-                } catch (Exception e) {
-                    p.Reject(e);
-                } finally {
-                    TraceContext.Instance.Leave();
-                }
-            }, null);
-
-            return p;
-        }
-
-
-        /// 
-        /// Starts the apartment thread
-        /// 
-        /// Promise which will be fullfiled when the syncronization
-        /// context will be ready to accept tasks.
-        protected override IPromise OnStart() {
-            m_worker.Start();
-            return m_threadStarted;
-        }
-
-        /// 
-        /// Posts quit message to the message loop of the apartment
-        /// 
-        /// Promise
-        protected override IPromise OnStop() {
-            m_syncContext.Post(x => Application.ExitThread(), null);
-            return m_threadTerminated;
-        }
-
-        void WorkerEntry() {
-            m_syncContext = new WindowsFormsSynchronizationContext();
-            SynchronizationContext.SetSynchronizationContext(m_syncContext);
-            m_enterPromise = new SyncContextPromise(m_syncContext);
-            m_threadStarted.Resolve();
-            m_enterPromise.Resolve();
-
-            Application.OleRequired();
-            Application.Run();
-
-            try {
-                OnShutdown();
-                m_threadTerminated.Resolve();
-            } catch(Exception err) {
-                m_threadTerminated.Reject(err);
-            }
-        }
-
-        /// 
-        /// Called from the STA apartment after the message loop is terminated, override this
-        /// method to handle apartment cleanup.
-        /// 
-        protected virtual void OnShutdown() {
-        }
-
-        protected override void Dispose(bool disposing) {
-            if (disposing) {
-                if (!m_threadTerminated.IsFulfilled)
-                    m_syncContext.Post(x => Application.ExitThread(), null);
-            }
-            base.Dispose(disposing);
-        }
-    }
-}
diff --git a/Implab/AbstractPromise.cs b/Implab/AbstractPromise.cs
--- a/Implab/AbstractPromise.cs
+++ b/Implab/AbstractPromise.cs
@@ -118,6 +118,8 @@ namespace Implab {
 
         public void Join(int timeout) {
             WaitResult(timeout);
+            if (IsRejected)
+                Rethrow();
         }
     }
 }
diff --git a/Implab/AbstractPromiseT.cs b/Implab/AbstractPromiseT.cs
deleted file mode 100644
--- a/Implab/AbstractPromiseT.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using System;
-using Implab.Parallels;
-
-namespace Implab {
-    public abstract class AbstractPromise : AbstractEvent.HandlerDescriptor>, IPromise {
-        public struct HandlerDescriptor {
-            readonly Action m_handler;
-            readonly Action m_success;
-            readonly Action m_error;
-            readonly Action m_cancel;
-            readonly PromiseEventType m_mask;
-
-            public HandlerDescriptor(Action success, Action error, Action cancel) {
-                m_success = success;
-                m_error = error;
-                m_cancel = cancel;
-
-                m_handler = null;
-                m_mask = 0;
-            }
-
-            public HandlerDescriptor(Action success, Action error, Action cancel) {
-                m_handler = success;
-                m_success = null;
-                m_error = error;
-                m_cancel = cancel;
-                m_mask = PromiseEventType.Success;
-            }
-
-            public HandlerDescriptor(Action handler, PromiseEventType mask) {
-                m_handler = handler;
-                m_mask = mask;
-                m_success = null;
-                m_error = null;
-                m_cancel = null;
-            }
-
-            public void SignalSuccess(T result) {
-                if (m_success != null) {
-                    try {
-                        m_success(result);
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                } else if ((m_mask & PromiseEventType.Success) != 0 && m_handler != null) {
-                    try {
-                        m_handler();
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                }
-            }
-
-            public void SignalError(Exception err) {
-                if (m_error != null) {
-                    try {
-                        m_error(err);
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                } else if ((m_mask & PromiseEventType.Error) != 0 && m_handler != null) {
-                    try {
-                        m_handler();
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                }
-            }
-
-            public void SignalCancel(Exception reason) {
-                if (m_cancel != null) {
-                    try {
-                        m_cancel(reason);
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                } else if ((m_mask & PromiseEventType.Cancelled) != 0 && m_handler != null) {
-                    try {
-                        m_handler();
-                        // Analysis disable once EmptyGeneralCatchClause
-                    } catch {
-                    }
-                }
-            }
-        }
-
-        public Type ResultType {
-            get {
-                return typeof(T);
-            }
-        }
-
-        public T Join() {
-            WaitResult(-1);
-            return m_result;
-        }
-        public T Join(int timeout) {
-            WaitResult(timeout);
-            return m_result;
-        }
-
-        void IPromise.Join() {
-            WaitResult(-1);
-        }
-        void IPromise.Join(int timeout) {
-            WaitResult(timeout);
-        }
-
-        public IPromise On(Action success, Action error, Action cancel) {
-            AddHandler(new HandlerDescriptor(success, error, cancel));
-            return this;
-        }
-
-        public IPromise On(Action success, Action error) {
-            AddHandler(new HandlerDescriptor(success, error, null));
-            return this;
-        }
-
-        public IPromise On(Action success) {
-            AddHandler(new HandlerDescriptor(success, null, null));
-            return this;
-        }
-
-        public IPromise On(Action handler, PromiseEventType events) {
-            AddHandler(new HandlerDescriptor(handler, events));
-            return this;
-        }
-
-        public IPromise On(Action success, Action error, Action cancel) {
-            AddHandler(new HandlerDescriptor(success, error, cancel));
-            return this;
-        }
-
-        public IPromise On(Action success, Action error) {
-            AddHandler(new HandlerDescriptor(success, error, null));
-            return this;
-        }
-
-        public IPromise On(Action success) {
-            AddHandler(new HandlerDescriptor(success, null, null));
-            return this;
-        }
-
-        IPromise IPromise.On(Action success, Action error, Action cancel) {
-            AddHandler(new HandlerDescriptor(success, error, cancel));
-            return this;
-        }
-
-        IPromise IPromise.On(Action success, Action error) {
-            AddHandler(new HandlerDescriptor(success, error, null));
-            return this;
-        }
-
-        IPromise IPromise.On(Action success) {
-            AddHandler(new HandlerDescriptor(success, null, null));
-            return this;
-        }
-
-        IPromise IPromise.On(Action handler, PromiseEventType events) {
-            AddHandler(new HandlerDescriptor(handler, events));
-            return this;
-        }
-
-        public IPromise Cast() {
-            return (IPromise)this;
-        }
-
-        #region implemented abstract members of AbstractPromise
-
-        protected override Signal GetFulfillSignal() {
-            var signal = new Signal();
-            AddHandler(new HandlerDescriptor(signal.Set, PromiseEventType.All));
-            return signal;
-        }
-
-        protected override void SignalHandler(HandlerDescriptor handler, int signal) {
-            switch (signal) {
-                case SUCCEEDED_STATE:
-                    handler.SignalSuccess(m_result);
-                    break;
-                case REJECTED_STATE:
-                    handler.SignalError(RejectReason);
-                    break;
-                case CANCELLED_STATE:
-                    handler.SignalCancel(CancellationReason);
-                    break;
-                default:
-                    throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", signal));
-            }
-        }
-
-        #endregion
-
-        T m_result;
-
-        protected void SetResult(T value) {
-            if (BeginSetResult()) {
-                m_result = value;
-                EndSetResult();
-            }
-        }
-    }
-}
-
diff --git a/Implab/AbstractPromise`1.cs b/Implab/AbstractPromise`1.cs
new file mode 100644
--- /dev/null
+++ b/Implab/AbstractPromise`1.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using Implab.Parallels;
+
+namespace Implab {
+    public class AbstractPromise : AbstractEvent>, IPromise {
+
+        class ResolvableSignal : IResolvable {
+            public Signal Signal { get; private set; }
+            public ResolvableSignal() {
+                Signal = new Signal();
+            }
+
+
+            public void Reject(Exception error) {
+                Signal.Set();
+            }
+
+            public void Resolve(T result) {
+                Signal.Set();
+            }
+        }
+
+        class ResolvableWrapper : IResolvable {
+            readonly IResolvable m_resolvable;
+            public ResolvableWrapper(IResolvable resolvable) {
+
+            }
+
+            public void Reject(Exception reason) {
+                m_resolvable.Reject(reason);
+            }
+
+            public void Resolve(T value) {
+                m_resolvable.Resolve();
+            }
+        }
+
+        PromiseState m_state;
+
+        T m_result;
+
+        Exception m_error;
+
+        public bool IsRejected {
+            get {
+                return m_state == PromiseState.Rejected;
+            }
+        }
+
+        public bool IsFulfilled {
+            get {
+                return m_state == PromiseState.Fulfilled;
+            }
+        }
+
+        public Exception RejectReason {
+            get {
+                return m_error;
+            }
+        }
+
+
+        internal void Resolve(T result) {
+            if (BeginTransit())
+                CompleteResolve();
+        }
+
+        internal void Reject(Exception reason) {
+            if (BeginTransit()) {
+                m_error = reason;
+                m_state = PromiseState.Rejected;
+                CompleteTransit();
+            }
+        }
+
+
+        #region implemented abstract members of AbstractPromise
+
+        protected override void SignalHandler(IResolvable handler) {
+            switch (m_state) {
+                case PromiseState.Fulfilled:
+                    handler.Resolve(m_result);
+                    break;
+                case PromiseState.Rejected:
+                    handler.Reject(RejectReason);
+                    break;
+                default:
+                    throw new InvalidOperationException(String.Format("Invalid promise signal: {0}", m_state));
+            }
+        }
+
+        protected override Signal GetFulfillSignal() {
+            var next = new ResolvableSignal();
+            Then(next);
+            return next.Signal;
+        }
+
+        #endregion
+
+        protected void CompleteResolve() {
+            m_state = PromiseState.Fulfilled;
+            CompleteTransit();
+        }
+
+        public Type ResultType {
+            get {
+                return typeof(void);
+            }
+        }
+
+
+        protected void Rethrow() {
+            Debug.Assert(m_error != null);
+            if (m_error is OperationCanceledException)
+                throw new OperationCanceledException("Operation cancelled", m_error);
+            else
+                throw new TargetInvocationException(m_error);
+        }
+
+        public void Then(IResolvable next) {
+            AddHandler(next);
+        }
+
+        public void Then(IResolvable next) {
+            AddHandler(new ResolvableWrapper(next));
+        }
+
+        public IPromise Cast() {
+            return (IPromise)this;
+        }
+
+        void IPromise.Join() {
+            WaitResult(-1);
+            if (IsRejected)
+                Rethrow();
+        }
+
+        void IPromise.Join(int timeout) {
+            WaitResult(timeout);
+            if (IsRejected)
+                Rethrow();
+        }
+
+        public T Join() {
+            WaitResult(-1);
+            if (IsRejected)
+                Rethrow();
+            return m_result;
+        }
+
+        public T Join(int timeout) {
+            WaitResult(timeout);
+            if (IsRejected)
+                Rethrow();
+            return m_result;
+        }
+    }
+}
+
diff --git a/Implab/AbstractTask.cs b/Implab/AbstractTask.cs
deleted file mode 100644
--- a/Implab/AbstractTask.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Threading;
-
-namespace Implab {
-    /// 
-    /// Базовый класс для реализации задачь. Задача представляет собой некторое
-    /// действие, которое можно иницировать и обработать результат его выполнения
-    ///  в виде обещания, для этого оно реализует интерфейс .
-    /// 
-    /// 
-    /// Данный класс определяет стандартное поведение при обработки результатов, в частности
-    /// обработку  и 
-    /// 
-    public abstract class AbstractTask : AbstractPromise {
-        int m_cancelationLock;
-
-        /// 
-        /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения.
-        /// 
-        /// true, if cancelation was locked, false otherwise.
-        protected bool LockCancelation() {
-            return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
-        }
-
-
-
-        protected void SetErrorInternal(Exception error) {
-            // unwrap 
-            while (error is PromiseTransientException && error.InnerException != null)
-                error = error.InnerException;
-            
-            if (error is OperationCanceledException)
-                SetCancelled(error);
-            else
-                SetError(error);
-        }
-
-        protected void SetCancelledInternal(Exception reason) {
-            SetCancelled(
-                reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason)
-            );
-        }
-    }
-}
-
diff --git a/Implab/AbstractTaskT.cs b/Implab/AbstractTaskT.cs
deleted file mode 100644
--- a/Implab/AbstractTaskT.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Threading;
-
-namespace Implab {
-    public abstract class AbstractTask : AbstractPromise {
-        int m_cancelationLock;
-
-        /// 
-        /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения.
-        /// 
-        /// true, if cancelation was locked, false otherwise.
-        protected bool LockCancelation() {
-            return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0);
-        }
-
-
-
-        protected void SetErrorInternal(Exception error) {
-            // unwrap 
-            while (error is PromiseTransientException && error.InnerException != null)
-                error = error.InnerException;
-
-            if (error is OperationCanceledException)
-                SetCancelled(error);
-            else
-                SetError(error);
-        }
-
-        protected void SetCancelledInternal(Exception reason) {
-            SetCancelled(
-                reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason)
-            );
-        }
-    }
-}
-
diff --git a/Implab/ActionChainTask.cs b/Implab/ActionChainTask.cs
deleted file mode 100644
--- a/Implab/ActionChainTask.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-
-namespace Implab {
-    public class ActionChainTask : ActionChainTaskBase, IResolvable {
-        readonly Func m_task;
-
-        /// 
-        /// Initializes a new instance of the  class.
-        /// 
-        /// The operation which will be performed when the  is called.
-        /// The error handler which will invoke when the  is called or when the task fails with an error.
-        /// The cancellation handler.
-        /// If set to true will automatically accept
-        ///  all cancel requests before the task is started with ,
-        /// after that all requests are directed to the task.
-        public ActionChainTask(Func task, Func error, Func cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve() {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    var p = m_task();
-                    p.On(SetResult, HandleErrorInternal, HandleCancelInternal);
-                    CancellationRequested(p.Cancel);
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-
-    }
-}
-
diff --git a/Implab/ActionChainTaskBase.cs b/Implab/ActionChainTaskBase.cs
deleted file mode 100644
--- a/Implab/ActionChainTaskBase.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Threading;
-
-namespace Implab {
-    public class ActionChainTaskBase : AbstractTask {
-        readonly Func m_error;
-        readonly Func m_cancel;
-
-        protected ActionChainTaskBase(Func error, Func cancel, bool autoCancellable) {
-            m_error = error;
-            m_cancel = cancel;
-            if (autoCancellable)
-                CancellationRequested(CancelOperation);
-        }
-
-        public void Reject(Exception error) {
-            if (LockCancelation())
-                HandleErrorInternal(error);
-        }
-
-        public override void CancelOperation(Exception reason) {
-            if (LockCancelation())
-                // отмена вызвана до начала выполнения задачи
-                HandleCancelInternal(reason);
-        }
-
-        protected void HandleCancelInternal(Exception reason) {
-            if (m_cancel != null) {
-                try {
-                    // вызываем обработчик отмены
-                    var p = m_cancel(reason);
-                    p.On(SetResult, HandleErrorInternal, SetCancelledInternal);
-                    // сообщаем асинхронной операции, что клиент уже не хочет получать результат
-                    // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены
-                    // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает
-                    // отдавать ли результат или подтвердить отмену (или вернуть ошибку).
-                    CancellationRequested(p.Cancel);
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetCancelledInternal(reason);
-            }
-        }
-
-        protected void HandleErrorInternal(Exception error) {
-            if (m_error != null) {
-                try {
-                    var p = m_error(error);
-                    p.On(SetResult, SetErrorInternal, SetCancelledInternal);
-                    CancellationRequested(p.Cancel);
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetErrorInternal(error);
-            }
-        }
-
-    }
-}
-
diff --git a/Implab/ActionChainTaskT.cs b/Implab/ActionChainTaskT.cs
deleted file mode 100644
--- a/Implab/ActionChainTaskT.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-
-namespace Implab {
-    public class ActionChainTask : ActionChainTaskBase, IDeferred {
-        readonly Func m_task;
-
-        public ActionChainTask(Func task, Func error, Func cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve(T value) {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    var p = m_task(value);
-                    p.On(SetResult, HandleErrorInternal, HandleCancelInternal);
-                    CancellationRequested(p.Cancel);
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-
-    }
-}
-
diff --git a/Implab/ActionTask.cs b/Implab/ActionTask.cs
deleted file mode 100644
--- a/Implab/ActionTask.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace Implab {
-    public class ActionTask : ActionTaskBase, IResolvable {
-        readonly Action m_task;
-        public ActionTask(Action task, Action error, Action cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve() {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    m_task();
-                    SetResult();
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
-
diff --git a/Implab/ActionTaskBase.cs b/Implab/ActionTaskBase.cs
deleted file mode 100644
--- a/Implab/ActionTaskBase.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-
-namespace Implab {
-    public class ActionTaskBase : AbstractTask {
-        readonly Action m_cancel;
-        readonly Action m_error;
-
-        protected ActionTaskBase( Action error, Action cancel, bool autoCancellable) {
-            m_error = error;
-            m_cancel = cancel;
-            if (autoCancellable)
-                CancellationRequested(CancelOperation);
-        }
-
-        public void Reject(Exception error) {
-            Safe.ArgumentNotNull(error, "error");
-            if (LockCancelation())
-                HandleErrorInternal(error);
-        }
-
-        public override void CancelOperation(Exception reason) {
-            if (LockCancelation())
-                HandleCancelInternal(reason);
-        }
-
-        protected void HandleErrorInternal(Exception error) {
-            if (m_error != null) {
-                try {
-                    m_error(error);
-                    SetResult();
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetErrorInternal(error);
-            }
-        }
-
-        protected void HandleCancelInternal(Exception error) {
-            if (m_cancel != null) {
-                try {
-                    m_cancel(error);
-                    SetResult();
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetCancelledInternal(error);
-            }
-        }
-    }
-}
-
diff --git a/Implab/ActionTaskT.cs b/Implab/ActionTaskT.cs
deleted file mode 100644
--- a/Implab/ActionTaskT.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace Implab {
-    public class ActionTask : ActionTaskBase, IDeferred {
-        readonly Action m_task;
-        public ActionTask(Action task, Action error, Action cancel, bool autoCancellable) : base(error,cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve(T value) {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    m_task(value);
-                    SetResult();
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
-
diff --git a/Implab/FailedPromise.cs b/Implab/FailedPromise.cs
deleted file mode 100644
--- a/Implab/FailedPromise.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System;
-using System.Reflection;
-
-namespace Implab {
-    public class FailedPromise : IPromise {
-        readonly Exception m_error;
-        public FailedPromise(Exception error) {
-            Safe.ArgumentNotNull(error, "error");
-            m_error = error;
-        }
-
-        #region IPromise implementation
-
-        public IPromise On(Action success, Action error, Action cancel) {
-            if (error != null) {
-                try {
-                    error(m_error);  
-                // Analysis disable once EmptyGeneralCatchClause
-                } catch {
-                }
-            }
-            return this;
-        }
-
-        public IPromise On(Action success, Action error) {
-            if (error != null) {
-                try {
-                    error(m_error);  
-                    // Analysis disable once EmptyGeneralCatchClause
-                } catch {
-                }
-            }
-            return this;
-        }
-
-        public IPromise On(Action success) {
-            return this;
-        }
-
-        public IPromise On(Action handler, PromiseEventType events) {
-            if ((events & PromiseEventType.Error) != 0) {
-                try {
-                    handler();
-                    // Analysis disable once EmptyGeneralCatchClause
-                } catch {
-                }
-            }
-            return this;
-        }
-
-        public IPromise Cast() {
-            return (IPromise)this;
-        }
-
-        public void Join() {
-            throw new TargetInvocationException(RejectReason);
-        }
-
-        public void Join(int timeout) {
-            throw new TargetInvocationException(RejectReason);
-        }
-
-        public virtual Type ResultType {
-            get {
-                return typeof(void);
-            }
-        }
-
-        public bool IsFulfilled {
-            get {
-                return true;
-            }
-        }
-
-        public bool IsCancelled {
-            get {
-                return false;
-            }
-        }
-
-        public Exception RejectReason {
-            get {
-                return m_error;
-            }
-        }
-
-        #endregion
-
-        #region ICancellable implementation
-
-        public void Cancel() {
-        }
-
-        public void Cancel(Exception reason) {
-        }
-
-        #endregion
-    }
-}
-
diff --git a/Implab/FailedPromiseT.cs b/Implab/FailedPromiseT.cs
deleted file mode 100644
--- a/Implab/FailedPromiseT.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Reflection;
-
-namespace Implab {
-    public class FailedPromise : FailedPromise, IPromise {
-        public FailedPromise(Exception error) : base(error) {
-        }
-
-        public IPromise On(Action success, Action error, Action cancel) {
-            if (error != null) {
-                try {
-                    error(RejectReason);  
-                    // Analysis disable once EmptyGeneralCatchClause
-                } catch {
-                }
-            }
-            return this;
-        }
-
-        public IPromise On(Action success, Action error) {
-            if (error != null) {
-                try {
-                    error(RejectReason);  
-                    // Analysis disable once EmptyGeneralCatchClause
-                } catch {
-                }
-            }
-            return this;
-        }
-
-        public IPromise On(Action success) {
-            return this;
-        }
-
-        T IPromise.Join() {
-            throw new TargetInvocationException(RejectReason);
-        }
-
-        T IPromise.Join(int timeout) {
-            throw new TargetInvocationException(RejectReason);
-        }
-
-
-        IPromise IPromise.On(Action success, Action error, Action cancel) {
-            On(success, error, cancel);
-            return this;
-        }
-
-        IPromise IPromise.On(Action success, Action error) {
-            On(success, error);
-            return this;
-        }
-
-        IPromise IPromise.On(Action success) {
-            On(success);
-            return this;
-        }
-
-        IPromise IPromise.On(Action handler, PromiseEventType events) {
-            On(handler, events);
-            return this;
-        }
-    }
-}
-
diff --git a/Implab/FuncChainTask.cs b/Implab/FuncChainTask.cs
deleted file mode 100644
--- a/Implab/FuncChainTask.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-
-namespace Implab {
-    public class FuncChainTask : FuncChainTaskBase, IResolvable {
-        readonly Func> m_task;
-
-        public FuncChainTask(Func> task, Func> error, Func> cancel, bool autoCancellable)
-            : base(error, cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve() {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    var operation = m_task();
-                    operation.On(SetResult, HandleErrorInternal, HandleCancelInternal);
-                    CancellationRequested(operation.Cancel);
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/Implab/FuncChainTaskBase.cs b/Implab/FuncChainTaskBase.cs
deleted file mode 100644
--- a/Implab/FuncChainTaskBase.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-
-namespace Implab {
-    public class FuncChainTaskBase : AbstractTask {
-        readonly Func> m_error;
-        readonly Func> m_cancel;
-
-        protected FuncChainTaskBase( Func> error, Func> cancel, bool autoCancellable) {
-            m_error = error;
-            m_cancel = cancel;
-            if (autoCancellable)
-                CancellationRequested(CancelOperation);
-        }
-
-        public void Reject(Exception error) {
-            if (LockCancelation())
-                HandleErrorInternal(error);
-        }
-
-        public override void CancelOperation(Exception reason) {
-            if (LockCancelation())
-                HandleCancelInternal(reason);
-        }
-
-        protected void HandleErrorInternal(Exception error) {
-            if (m_error != null) {
-                try {
-                    var p = m_error(error);
-                    p.On(SetResult, SetErrorInternal, SetCancelledInternal);
-                    CancellationRequested(p.Cancel);
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetErrorInternal(error);
-            }
-        }
-
-        protected void HandleCancelInternal(Exception reason) {
-            if (m_cancel != null) {
-                try {
-                    var p = m_cancel(reason);
-                    p.On(SetResult, HandleErrorInternal, SetCancelledInternal);
-                    CancellationRequested(p.Cancel);
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetCancelledInternal(reason);
-            }
-        }
-    }
-}
-
diff --git a/Implab/FuncChainTaskT.cs b/Implab/FuncChainTaskT.cs
deleted file mode 100644
--- a/Implab/FuncChainTaskT.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-
-namespace Implab {
-    public class FuncChainTask : FuncChainTaskBase, IDeferred {
-        readonly Func> m_task;
-
-        public FuncChainTask(Func> task, Func> error, Func> cancel, bool autoCancellable) : base(error, cancel, autoCancellable){
-            m_task = task;
-        }
-
-        public void Resolve(TArg value) {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    var operation = m_task(value);
-                    operation.On(SetResult, HandleErrorInternal, SetCancelled);
-                    CancellationRequested(operation.Cancel);
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/Implab/FuncTask.cs b/Implab/FuncTask.cs
deleted file mode 100644
--- a/Implab/FuncTask.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Threading;
-
-namespace Implab {
-    public class FuncTask : FuncTaskBase, IResolvable {
-        readonly Func m_task;
-
-        public FuncTask(Func task, Func error, Func cancel, bool autoCancellable) : base(error, cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve() {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    SetResult(m_task());
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
-
diff --git a/Implab/FuncTaskBase.cs b/Implab/FuncTaskBase.cs
deleted file mode 100644
--- a/Implab/FuncTaskBase.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-
-namespace Implab {
-    public class FuncTaskBase : AbstractTask {
-        readonly Func m_cancel;
-        readonly Func m_error;
-
-        protected FuncTaskBase( Func error, Func cancel, bool autoCancellable) {
-            m_error = error;
-            m_cancel = cancel;
-            if (autoCancellable)
-                CancellationRequested(CancelOperation);
-        }
-
-        public void Reject(Exception error) {
-            Safe.ArgumentNotNull(error, "error");
-            if (LockCancelation())
-                HandleErrorInternal(error);
-        }
-
-        protected void HandleErrorInternal(Exception error) {
-            if (m_error != null) {
-                try {
-                    SetResult(m_error(error));
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetErrorInternal(error);
-            }
-        }
-
-        public override void CancelOperation(Exception reason) {
-            if (LockCancelation())
-                HandleCancelInternal(reason);
-        }
-
-        protected void HandleCancelInternal(Exception reason) {
-            if (m_cancel != null) {
-                try {
-                    SetResult(m_cancel(reason));
-                } catch (Exception err) {
-                    SetErrorInternal(err);
-                }
-            } else {
-                SetCancelledInternal(reason);
-            }
-        }
-
-    }
-}
-
diff --git a/Implab/FuncTaskT.cs b/Implab/FuncTaskT.cs
deleted file mode 100644
--- a/Implab/FuncTaskT.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-
-namespace Implab {
-    public class FuncTask : FuncTaskBase, IDeferred {
-        readonly Func m_task;
-
-        public FuncTask(Func task, Func error,Func cancel, bool autoCancellable) :  base(error,cancel, autoCancellable) {
-            m_task = task;
-        }
-
-        public void Resolve(TArg value) {
-            if (m_task != null && LockCancelation()) {
-                try {
-                    SetResult(m_task(value));
-                } catch(Exception err) {
-                    SetErrorInternal(err);
-                }
-            }
-        }
-    }
-}
-
diff --git a/Implab/IProgressHandler.cs b/Implab/IProgressHandler.cs
deleted file mode 100644
--- a/Implab/IProgressHandler.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Implab {
-    public interface IProgressHandler {
-        string Message {
-            get;
-            set;
-        }
-        float CurrentProgress {
-            get;
-            set;
-        }
-        void InitProgress(float current, float max, string message);
-    }
-}
diff --git a/Implab/IProgressNotifier.cs b/Implab/IProgressNotifier.cs
deleted file mode 100644
--- a/Implab/IProgressNotifier.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Implab
-{
-    public interface IProgressNotifier
-    {
-        event EventHandler> MessageUpdated;
-        event EventHandler> ProgressUpdated;
-        event EventHandler ProgressInit;
-    }
-}
diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs
--- a/Implab/IPromise.cs
+++ b/Implab/IPromise.cs
@@ -37,5 +37,9 @@ namespace Implab {
         /// Преобразует результат обещания к заданному типу и возвращает новое обещание.
         /// 
         IPromise Cast();
+
+        void Join();
+
+        void Join(int timeout);
     }
 }
diff --git a/Implab/IPromiseT.cs b/Implab/IPromiseT.cs
--- a/Implab/IPromiseT.cs
+++ b/Implab/IPromiseT.cs
@@ -3,7 +3,7 @@
 namespace Implab {
     public interface IPromise : IPromise {
 
-        void On(Action success, Action error);
+        void Then(IResolvable next);
 
         new T Join();
 
diff --git a/Implab/IResolvable`1.cs b/Implab/IResolvable`1.cs
--- a/Implab/IResolvable`1.cs
+++ b/Implab/IResolvable`1.cs
@@ -2,7 +2,7 @@ using System;
 
 namespace Implab {
     
-    public interface IResolvable {
+    public interface IResolvable {
         void Resolve(T value);
 
         void Reject(Exception reason);
diff --git a/Implab/ITaskController.cs b/Implab/ITaskController.cs
deleted file mode 100644
--- a/Implab/ITaskController.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace Implab {
-    public interface ITaskController: IProgressHandler, ICancellable {
-        bool IsCancelled {
-            get;
-        }
-
-        event EventHandler Cancelled;
-    }
-}
diff --git a/Implab/ProgressInitEventArgs.cs b/Implab/ProgressInitEventArgs.cs
deleted file mode 100644
--- a/Implab/ProgressInitEventArgs.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Implab
-{
-    [Serializable]
-    public class ProgressInitEventArgs: EventArgs
-    {
-        public float MaxProgress
-        {
-            get;
-            private set;
-        }
-
-        public float CurrentProgress
-        {
-            get;
-            private set;
-        }
-
-        public string Message
-        {
-            get;
-            private set;
-        }
-
-        public ProgressInitEventArgs(float current, float max, string message)
-        {
-            this.MaxProgress = max;
-            this.CurrentProgress = current;
-            this.Message = message;
-        }
-    }
-}
diff --git a/Implab/PromiseActionReaction.cs b/Implab/PromiseActionReaction.cs
new file mode 100644
--- /dev/null
+++ b/Implab/PromiseActionReaction.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Diagnostics;
+
+namespace Implab {
+    class PromiseActionReaction : PromiseReaction {
+        readonly Action m_fulfilled;
+
+        readonly Action m_rejected;
+
+        readonly Deferred m_next;
+
+        public PromiseActionReaction(Action fulfilled, Action rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => {
+                    fulfilled();
+                    next.Resolve();
+                };
+
+            if (rejected != null)
+                m_rejected = (x) => {
+                    rejected(x);
+                    next.Resolve();
+                };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Func fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Action fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => {
+                    fulfilled();
+                    next.Resolve();
+                };
+
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Func fulfilled, Action rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+
+            if (rejected != null)
+                m_rejected = (x) => {
+                    rejected(x);
+                    next.Resolve();
+                };
+            m_next = next;
+        }
+
+
+        protected override bool HasFulfilHandler => m_fulfilled != null;
+
+        protected override bool HasRejectHandler => m_rejected != null;
+
+        protected override void DefaultReject(Exception reason) {
+            m_next.Reject(reason);
+        }
+
+        protected override void DefaultResolve() {
+            m_next.Resolve();
+        }
+
+        protected override void RejectImpl(Exception reason) {
+            try {
+                m_rejected(reason);
+            } catch (Exception e){
+                m_next.Reject(e);
+            }
+        }
+
+        protected override void ResolveImpl() {
+            try {
+                m_fulfilled();
+            } catch (Exception e){
+                m_next.Reject(e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Implab/PromiseActionReaction`1.cs b/Implab/PromiseActionReaction`1.cs
new file mode 100644
--- /dev/null
+++ b/Implab/PromiseActionReaction`1.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Diagnostics;
+
+namespace Implab {
+    class PromiseActionReaction : PromiseReaction {
+        readonly Action m_fulfilled;
+
+        readonly Action m_rejected;
+
+        readonly Deferred m_next;
+
+        public PromiseActionReaction(Action fulfilled, Action rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = (x) => {
+                    fulfilled(x);
+                    next.Resolve();
+                };
+
+            if (rejected != null)
+                m_rejected = (x) => {
+                    rejected(x);
+                    next.Resolve();
+                };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Func fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = (x) => { next.Resolve(fulfilled(x)); };
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Action fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = (x) => {
+                    fulfilled(x);
+                    next.Resolve();
+                };
+
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseActionReaction(Func fulfilled, Action rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = (x) => { next.Resolve(fulfilled(x)); };
+
+            if (rejected != null)
+                m_rejected = (x) => {
+                    rejected(x);
+                    next.Resolve();
+                };
+            m_next = next;
+        }
+
+        protected override bool HasFulfilHandler => m_fulfilled != null;
+
+        protected override bool HasRejectHandler => m_rejected != null;
+
+        protected override void DefaultReject(Exception reason) {
+            m_next.Reject(reason);
+        }
+
+        protected override void DefaultResolve(T result) {
+            m_next.Resolve();
+        }
+
+        protected override void RejectImpl(Exception reason) {
+            try {
+                m_rejected(reason);
+            } catch (Exception e) {
+                m_next.Reject(e);
+            }
+        }
+
+        protected override void ResolveImpl(T result) {
+            try {
+                m_fulfilled(result);
+            } catch (Exception e) {
+                m_next.Reject(e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Implab/PromiseAwaiter.cs b/Implab/PromiseAwaiter.cs
deleted file mode 100644
--- a/Implab/PromiseAwaiter.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace Implab {
-    public struct PromiseAwaiter : INotifyCompletion {
-        readonly IPromise m_promise;
-
-        public PromiseAwaiter(IPromise promise) {
-            m_promise = promise;
-        }
-
-        public void OnCompleted (Action continuation) {
-            if (m_promise != null)
-                m_promise.On(continuation, PromiseEventType.All);
-        }
-
-        public void GetResult() {
-            m_promise.Join();
-        }
-
-        public bool IsCompleted {
-            get {
-                return m_promise.IsFulfilled;
-            }
-        }
-    }
-}
-
diff --git a/Implab/PromiseAwaiterT.cs b/Implab/PromiseAwaiterT.cs
deleted file mode 100644
--- a/Implab/PromiseAwaiterT.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace Implab {
-    public struct PromiseAwaiter : INotifyCompletion {
-        readonly IPromise m_promise;
-
-        public PromiseAwaiter(IPromise promise) {
-            m_promise = promise;
-        }
-
-        public void OnCompleted (Action continuation) {
-            if (m_promise != null)
-                m_promise.On(continuation, PromiseEventType.All);
-        }
-
-        public T GetResult() {
-            return m_promise.Join();
-        }
-
-        public bool IsCompleted {
-            get {
-                return m_promise.IsFulfilled;
-            }
-        }
-    }
-}
-
diff --git a/Implab/PromiseEventType.cs b/Implab/PromiseEventType.cs
deleted file mode 100644
--- a/Implab/PromiseEventType.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-
-namespace Implab {
-    [Flags]
-    public enum PromiseEventType {
-        Success = 1,
-        Error = 2,
-        Cancelled = 4,
-        /// 
-        /// Завершено успешно, либо возникла ошибка, 
-        /// 
-        All = 7,
-        /// 
-        /// Заврешено успешно, либо возникла ошибка.
-        /// 
-        Complete = 3,
-
-        ErrorOrCancel = 6
-    }
-}
-
diff --git a/Implab/PromiseFuncReaction`1.cs b/Implab/PromiseFuncReaction`1.cs
new file mode 100644
--- /dev/null
+++ b/Implab/PromiseFuncReaction`1.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Diagnostics;
+
+namespace Implab {
+    class PromiseFuncReaction : PromiseReaction {
+        readonly Action m_fulfilled;
+
+        readonly Action m_rejected;
+
+        readonly Deferred m_next;
+
+        public PromiseFuncReaction(Func fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseFuncReaction(Func> fulfilled, Func> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+            m_next = next;
+        }
+
+        public PromiseFuncReaction(Func fulfilled, Func> rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+
+            m_next = next;
+        }
+
+        public PromiseFuncReaction(Func> fulfilled, Func rejected, Deferred next, IDispatcher dispatcher) : base(dispatcher) {
+            if (fulfilled != null)
+                m_fulfilled = () => { next.Resolve(fulfilled()); };
+            if (rejected != null)
+                m_rejected = (e) => { next.Resolve(rejected(e)); };
+
+            m_next = next;
+        }
+
+
+        protected override bool HasFulfilHandler => m_fulfilled != null;
+
+        protected override bool HasRejectHandler => m_rejected != null;
+
+        protected override void DefaultReject(Exception reason) {
+            m_next.Reject(reason);
+        }
+
+        protected override void DefaultResolve() {
+            throw new NotImplementedException();
+        }
+
+        protected override void RejectImpl(Exception reason) {
+            try {
+                m_rejected(reason);
+            } catch (Exception e){
+                m_next.Reject(e);
+            }
+        }
+
+        protected override void ResolveImpl() {
+            try {
+                m_fulfilled();
+            } catch (Exception e){
+                m_next.Reject(e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Implab/PromiseReaction.cs b/Implab/PromiseReaction.cs
--- a/Implab/PromiseReaction.cs
+++ b/Implab/PromiseReaction.cs
@@ -1,35 +1,45 @@
 using System;
 
 namespace Implab {
-    public class PromiseReaction : IResolvable {
-        IDispatcher m_dispatcher;
+    abstract class PromiseReaction : IResolvable {
+        readonly IDispatcher m_dispatcher;
+
+        protected PromiseReaction(IDispatcher dispatcher) {
+            m_dispatcher = dispatcher;
+        }
 
-        Action m_onFulfilledJob;
+        protected abstract bool HasFulfilHandler {
+            get;
+        }
 
-        Action m_onRejectedJob;
-
-        IResolvable m_next;
+        protected abstract bool HasRejectHandler {
+            get;
+        }
 
         public void Reject(Exception error) {
-            if (m_onRejectedJob != null) {
-                if (m_dispatcher != null)
-                    m_dispatcher.Enqueue(() => m_onRejectedJob(error));
-                else
-                    m_onRejectedJob(error);
-            } else {
-                m_next.Reject(error);
-            }
+            if (!HasRejectHandler)
+                DefaultReject(error);
+            else if (m_dispatcher != null)
+                m_dispatcher.Enqueue(() => RejectImpl(error));
+            else
+                RejectImpl(error);
         }
 
         public void Resolve() {
-            if (m_onRejectedJob != null) {
-                if (m_dispatcher != null)
-                    m_dispatcher.Enqueue( m_onFulfilledJob);
-                else
-                    m_onFulfilledJob();
-            } else {
-                m_next.Resolve();
-            }
+            if (!HasFulfilHandler)
+                DefaultResolve();
+            else if (m_dispatcher != null)
+                m_dispatcher.Enqueue(ResolveImpl);
+            else
+                ResolveImpl();
         }
+
+        protected abstract void ResolveImpl();
+
+        protected abstract void RejectImpl(Exception reason);
+
+        protected abstract void DefaultResolve();
+
+        protected abstract void DefaultReject(Exception reason);
     }
 }
\ No newline at end of file
diff --git a/Implab/PromiseReactionJob.cs b/Implab/PromiseReactionJob.cs
deleted file mode 100644
--- a/Implab/PromiseReactionJob.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System;
-using System.Diagnostics;
-
-namespace Implab
-{
-    class PromiseReactionJob {
-        public static Action Create(Action handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return (v) => {
-                try {
-                    handler(v);
-                    next.Resolve();
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return (v) => {
-                try {
-                    next.Resolve(handler(v));
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return (v) => {
-                try {
-                    next.Resolve(handler(v));
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func> handler, Deferred next) {
-            Debug.Assert(handler != null);
-            return (v) => {
-                try {
-                    next.Resolve(handler(v));
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Action handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return () => {
-                try {
-                    handler();
-                    next.Resolve();
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return () => {
-                try {
-                    next.Resolve(handler());
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func handler, Deferred next) {
-            Debug.Assert(handler != null);
-            
-            return () => {
-                try {
-                    next.Resolve(handler());
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-
-        public static Action Create(Func> handler, Deferred next) {
-            Debug.Assert(handler != null);
-            return () => {
-                try {
-                    next.Resolve(handler());
-                } catch(Exception err) {
-                    next.Reject(err);
-                }
-            };
-        }
-    }
-}
\ No newline at end of file
diff --git a/Implab/PromiseReaction`1.cs b/Implab/PromiseReaction`1.cs
--- a/Implab/PromiseReaction`1.cs
+++ b/Implab/PromiseReaction`1.cs
@@ -1,25 +1,45 @@
 using System;
 
 namespace Implab {
-    public class PromiseReaction : IResolvable {
-        IDispatcher m_dispatcher;
+    abstract class PromiseReaction : IResolvable {
+        readonly IDispatcher m_dispatcher;
+
+        protected PromiseReaction(IDispatcher dispatcher) {
+            m_dispatcher = dispatcher;
+        }
 
-        Action m_onFulfilledJob;
+        protected abstract bool HasFulfilHandler {
+            get;
+        }
 
-        Action m_onRejectedJob;
+        protected abstract bool HasRejectHandler {
+            get;
+        }
 
         public void Reject(Exception error) {
-            if (m_dispatcher != null)
-                m_dispatcher.Enqueue(() => m_onRejectedJob(error));
+            if (!HasRejectHandler)
+                DefaultReject(error);
+            else if (m_dispatcher != null)
+                m_dispatcher.Enqueue(() => RejectImpl(error));
             else
-                m_onRejectedJob(error);
+                RejectImpl(error);
         }
 
         public void Resolve(T result) {
-            if (m_dispatcher != null)
-                m_dispatcher.Enqueue(() => m_onFulfilledJob(result));
+            if (!HasFulfilHandler)
+                DefaultResolve(result);
+            else if (m_dispatcher != null)
+                m_dispatcher.Enqueue(() => ResolveImpl(result));
             else
-                m_onFulfilledJob(result);
+                ResolveImpl(result);
         }
+
+        protected abstract void ResolveImpl(T result);
+
+        protected abstract void RejectImpl(Exception reason);
+
+        protected abstract void DefaultResolve(T result);
+
+        protected abstract void DefaultReject(Exception reason);
     }
 }
\ No newline at end of file
diff --git a/Implab/PromiseT.cs b/Implab/PromiseT.cs
deleted file mode 100644
--- a/Implab/PromiseT.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using System.Diagnostics;
-using Implab.Parallels;
-
-namespace Implab {
-
-    /// 
-    /// Класс для асинхронного получения результатов. Так называемое "обещание".
-    /// 
-    /// Тип получаемого результата
-    /// 
-    /// Сервис при обращении к его методу дает обещаиние о выполнении операции,
-    /// клиент получив такое обещание может установить ряд обратных вызово для получения
-    /// событий выполнения обещания, тоесть завершения операции и предоставлении результатов.
-    /// 
-    /// Обещение может быть как выполнено, так и выполнено с ошибкой. Для подписки на
-    /// данные события клиент должен использовать методы Then.
-    /// 
-    /// 
-    /// Сервис, в свою очередь, по окончанию выполнения операции (возможно с ошибкой),
-    /// использует методы Resolve либо Reject для оповещения клиетна о
-    /// выполнении обещания.
-    /// 
-    /// 
-    /// Если сервер успел выполнить обещание еще до того, как клиент на него подписался,
-    /// то в момент подписки клиента будут вызваны соответсвующие события в синхронном
-    /// режиме и клиент будет оповещен в любом случае. Иначе, обработчики добавляются в
-    /// список в порядке подписания и в этом же порядке они будут вызваны при выполнении
-    /// обещания.
-    /// 
-    /// 
-    /// Обрабатывая результаты обещания можно преобразовывать результаты либо инициировать
-    /// связанные асинхронные операции, которые также возвращают обещания. Для этого следует
-    /// использовать соответствующую форму методе Then.
-    /// 
-    /// 
-    /// Также хорошим правилом является то, что Resolve и Reject должен вызывать
-    /// только инициатор обещания иначе могут возникнуть противоречия.
-    /// 
-    /// 
-    public class Promise : AbstractPromise, IDeferred {
-
-        public static IPromise FromResult(T value) {
-            return new SuccessPromise