##// END OF EJS Templates
implemeted new cancellable promises concept
cin -
r10:aa33d0bb8c0c promises
parent child
Show More
@@ -0,0 +1,16
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6
7 namespace Implab.Test {
8 class PromiseHelper {
9 public static Promise<T> Sleep<T>(int timeout, T retVal) {
10 return AsyncPool.Invoke(() => {
11 Thread.Sleep(timeout);
12 return retVal;
13 });
14 }
15 }
16 }
@@ -1,12 +1,13
1 1 syntax: glob
2 2 Implab.Test/bin/
3 3 *.user
4 4 Implab.Test/obj/
5 5 *.userprefs
6 6 Implab/bin/
7 7 Implab/obj/
8 8 TestResults/
9 9 Implab.Fx/obj/
10 10 Implab.Fx/bin/
11 11 Implab.Fx.Test/bin/
12 12 Implab.Fx.Test/obj/
13 _ReSharper.Implab/
@@ -1,101 +1,127
1 1 using System;
2 2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Implab;
4 3 using System.Reflection;
5 4 using System.Threading;
6 5
7 namespace Implab.Tests
6 namespace Implab.Test
8 7 {
9 8 [TestClass]
10 9 public class AsyncTests
11 10 {
12 11 [TestMethod]
13 12 public void ResolveTest ()
14 13 {
15 14 int res = -1;
16 15 var p = new Promise<int> ();
17 16 p.Then (x => res = x);
18 17 p.Resolve (100);
19 18
20 19 Assert.AreEqual (res, 100);
21 20 }
22 21
23 22 [TestMethod]
24 23 public void RejectTest ()
25 24 {
26 25 int res = -1;
27 26 Exception err = null;
28 27
29 28 var p = new Promise<int> ();
30 29 p.Then (x => res = x, e => err = e);
31 30 p.Reject (new ApplicationException ("error"));
32 31
33 32 Assert.AreEqual (res, -1);
34 33 Assert.AreEqual (err.Message, "error");
35 34
36 35 }
37 36
38 37 [TestMethod]
39 38 public void JoinSuccessTest ()
40 39 {
41 40 var p = new Promise<int> ();
42 41 p.Resolve (100);
43 42 Assert.AreEqual (p.Join (), 100);
44 43 }
45 44
46 45 [TestMethod]
47 46 public void JoinFailTest ()
48 47 {
49 48 var p = new Promise<int> ();
50 49 p.Reject (new ApplicationException ("failed"));
51 50
52 51 try {
53 52 p.Join ();
54 53 throw new ApplicationException ("WRONG!");
55 54 } catch (TargetInvocationException err) {
56 55 Assert.AreEqual (err.InnerException.Message, "failed");
57 56 } catch {
58 57 Assert.Fail ("Got wrong excaption");
59 58 }
60 59 }
61 60
62 61 [TestMethod]
63 62 public void MapTest ()
64 63 {
65 64 var p = new Promise<int> ();
66 65
67 66 var p2 = p.Map (x => x.ToString ());
68 67 p.Resolve (100);
69 68
70 69 Assert.AreEqual (p2.Join (), "100");
71 70 }
72 71
73 72 [TestMethod]
74 73 public void ChainTest ()
75 74 {
76 75 var p1 = new Promise<int> ();
77 76
78 77 var p3 = p1.Chain (x => {
79 78 var p2 = new Promise<string> ();
80 79 p2.Resolve (x.ToString ());
81 80 return p2;
82 81 });
83 82
84 83 p1.Resolve (100);
85 84
86 85 Assert.AreEqual (p3.Join (), "100");
87 86 }
88 87
89 88 [TestMethod]
90 89 public void PoolTest ()
91 90 {
92 91 var pid = Thread.CurrentThread.ManagedThreadId;
93 var p = AsyncPool.Invoke (() => {
94 return Thread.CurrentThread.ManagedThreadId;
95 });
92 var p = AsyncPool.Invoke (() => Thread.CurrentThread.ManagedThreadId);
96 93
97 94 Assert.AreNotEqual (pid, p.Join ());
98 95 }
96
97 [TestMethod]
98 public void ComplexCase1Test() {
99 var flags = new bool[3];
100
101 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map)
102
103 var p = PromiseHelper
104 .Sleep(200, "Alan")
105 .Cancelled(() => flags[0] = true)
106 .Chain(x =>
107 PromiseHelper
108 .Sleep(200, "Hi, " + x)
109 .Map( y => y )
110 .Cancelled(() => flags[1] = true)
111 )
112 .Cancelled(() => flags[2] = true);
113 Thread.Sleep(300);
114 p.Cancel();
115 try {
116 Assert.AreEqual(p.Join(), "Hi, Alan");
117 Assert.Fail("Shouldn't get here");
118 } catch(OperationCanceledException) {
119 }
120
121 Assert.IsFalse(flags[0]);
122 Assert.IsTrue(flags[1]);
123 Assert.IsTrue(flags[2]);
124 }
99 125 }
100 126 }
101 127
@@ -1,65 +1,66
1 1 ο»Ώ<?xml version="1.0" encoding="utf-8"?>
2 2 <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <PropertyGroup>
4 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 6 <ProductVersion>
7 7 </ProductVersion>
8 8 <SchemaVersion>2.0</SchemaVersion>
9 9 <ProjectGuid>{63F92C0C-61BF-48C0-A377-8D67C3C661D0}</ProjectGuid>
10 10 <OutputType>Library</OutputType>
11 11 <AppDesignerFolder>Properties</AppDesignerFolder>
12 12 <RootNamespace>Implab.Test</RootNamespace>
13 13 <AssemblyName>Implab.Test</AssemblyName>
14 14 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
15 15 <FileAlignment>512</FileAlignment>
16 16 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
17 17 </PropertyGroup>
18 18 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
19 19 <DebugSymbols>true</DebugSymbols>
20 20 <DebugType>full</DebugType>
21 21 <Optimize>false</Optimize>
22 22 <OutputPath>bin\Debug\</OutputPath>
23 23 <DefineConstants>DEBUG;TRACE</DefineConstants>
24 24 <ErrorReport>prompt</ErrorReport>
25 25 <WarningLevel>4</WarningLevel>
26 26 </PropertyGroup>
27 27 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
28 28 <DebugType>pdbonly</DebugType>
29 29 <Optimize>true</Optimize>
30 30 <OutputPath>bin\Release\</OutputPath>
31 31 <DefineConstants>TRACE</DefineConstants>
32 32 <ErrorReport>prompt</ErrorReport>
33 33 <WarningLevel>4</WarningLevel>
34 34 </PropertyGroup>
35 35 <ItemGroup>
36 36 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
37 37 <Reference Include="System" />
38 38 <Reference Include="System.Core">
39 39 <RequiredTargetFramework>3.5</RequiredTargetFramework>
40 40 </Reference>
41 41 </ItemGroup>
42 42 <ItemGroup>
43 43 <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
44 44 <Visible>False</Visible>
45 45 </CodeAnalysisDependentAssemblyPaths>
46 46 </ItemGroup>
47 47 <ItemGroup>
48 48 <Compile Include="AsyncTests.cs" />
49 <Compile Include="PromiseHelper.cs" />
49 50 <Compile Include="Properties\AssemblyInfo.cs" />
50 51 </ItemGroup>
51 52 <ItemGroup>
52 53 <ProjectReference Include="..\Implab\Implab.csproj">
53 54 <Project>{99B95D0D-9CF9-4F70-8ADF-F4D0AA5CB0D9}</Project>
54 55 <Name>Implab</Name>
55 56 </ProjectReference>
56 57 </ItemGroup>
57 58 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
58 59 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
59 60 Other similar extension points exist, see Microsoft.Common.targets.
60 61 <Target Name="BeforeBuild">
61 62 </Target>
62 63 <Target Name="AfterBuild">
63 64 </Target>
64 65 -->
65 66 </Project> No newline at end of file
1 NO CONTENT: modified file, binary diff hidden
@@ -1,33 +1,40
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab
7 7 {
8 8 public interface IPromise
9 9 {
10 10 /// <summary>
11 11 /// Check whereather the promise has no more than one dependent promise.
12 12 /// </summary>
13 13 bool IsExclusive
14 14 {
15 15 get;
16 16 }
17 17
18 18 /// <summary>
19 19 /// The current state of the promise.
20 20 /// </summary>
21 21 PromiseState State
22 22 {
23 23 get;
24 24 }
25 25
26 26 /// <summary>
27 27 /// Tries to cancel the promise or the complete chain.
28 28 /// </summary>
29 29 /// <param name="dependencies">Try to cancel the whole promise chain, the parent promise will be cancelled only if it has only one promise</param>
30 30 /// <returns></returns>
31 31 bool Cancel(bool dependencies);
32
33 /// <summary>
34 /// Registers handler for the case when the promise is cencelled. If the promise already cancelled the
35 /// handler will be invoked immediatelly.
36 /// </summary>
37 /// <param name="handler">The handler</param>
38 void HandleCancelled(Action handler);
32 39 }
33 40 }
@@ -1,443 +1,459
1 1 using System;
2 2 using System.Collections.Generic;
3 using System.Linq;
4 3 using System.Reflection;
5 using System.Text;
6 4 using System.Diagnostics;
7 5 using System.Threading;
8 6
9 7 namespace Implab {
10 8
11 9 public delegate void ErrorHandler(Exception e);
12 10
13 public delegate void ResultHandler<T>(T result);
14 public delegate TNew ResultMapper<TSrc, TNew>(TSrc result);
15 public delegate Promise<TNew> ChainedOperation<TSrc, TNew>(TSrc result);
11 public delegate void ResultHandler<in T>(T result);
12 public delegate TNew ResultMapper<in TSrc, out TNew>(TSrc result);
13 public delegate Promise<TNew> ChainedOperation<in TSrc, TNew>(TSrc result);
16 14
17 15 /// <summary>
18 16 /// Класс для асинхронного получСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Π’Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ "ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅".
19 17 /// </summary>
20 18 /// <typeparam name="T">Π’ΠΈΠΏ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°</typeparam>
21 19 /// <remarks>
22 20 /// <para>БСрвис ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Π΅Π³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ Π΄Π°Π΅Ρ‚ ΠΎΠ±Π΅Ρ‰Π°ΠΈΠ½ΠΈΠ΅ ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ,
23 21 /// ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ряд ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎ для получСния
24 22 /// событий выполнСния обСщания, Ρ‚ΠΎΠ΅ΡΡ‚ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈ прСдоставлСнии Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².</para>
25 23 /// <para>
26 24 /// ΠžΠ±Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ с ошибкой. Для подписки Π½Π°
27 25 /// Π΄Π°Π½Π½Ρ‹Π΅ события ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Then</c>.
28 26 /// </para>
29 27 /// <para>
30 28 /// БСрвис, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ (Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ с ошибкой),
31 29 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ <c>Resolve</c> Π»ΠΈΠ±ΠΎ <c>Reject</c> для оповСщСния ΠΊΠ»ΠΈΠ΅Ρ‚Π½Π° ΠΎ
32 30 /// Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ обСщания.
33 31 /// </para>
34 32 /// <para>
35 33 /// Если сСрвСр успСл Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π΅Ρ‰Π΅ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π° Π½Π΅Π³ΠΎ подписался,
36 34 /// Ρ‚ΠΎ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ подписки ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΠ²ΡƒΡŽΡ‰ΠΈΠ΅ события Π² синхронном
37 35 /// Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ Π² любом случаС. Π˜Π½Π°Ρ‡Π΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ Π²
38 36 /// список Π² порядкС подписания ΠΈ Π² этом ΠΆΠ΅ порядкС ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ
39 37 /// обСщания.
40 38 /// </para>
41 39 /// <para>
42 40 /// ΠžΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ обСщания ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π»ΠΈΠ±ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ
43 41 /// связанныС асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ обСщания. Для этого слСдуСт
44 42 /// ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Ρ„ΠΎΡ€ΠΌΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ <c>Then</c>.
45 43 /// </para>
46 44 /// <para>
47 45 /// Π’Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ <c>Resolve</c> ΠΈ <c>Reject</c> Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ
48 46 /// Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ обСщания ΠΈΠ½Π°Ρ‡Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ противорСчия.
49 47 /// </para>
50 48 /// </remarks>
51 49 public class Promise<T> : IPromise {
52 50
53 51 struct ResultHandlerInfo {
54 52 public ResultHandler<T> resultHandler;
55 53 public ErrorHandler errorHandler;
56 54 }
57 55
58 IPromise m_parent;
56 readonly IPromise m_parent;
59 57
60 58 LinkedList<ResultHandlerInfo> m_resultHandlers = new LinkedList<ResultHandlerInfo>();
61 59 LinkedList<Action> m_cancelHandlers = new LinkedList<Action>();
62 60
63 object m_lock = new Object();
64 bool m_cancellable;
61 readonly object m_lock = new Object();
62 readonly bool m_cancellable;
63 int m_childrenCount = 0;
65 64
66 65 PromiseState m_state;
67 66 T m_result;
68 67 Exception m_error;
69 68
70 int m_childrenCount;
71
72 69 public Promise() {
73 70 m_cancellable = true;
74 71 }
75 72
76 73 public Promise(IPromise parent, bool cancellable) {
77 74 m_cancellable = cancellable;
78 75 m_parent = parent;
76 if (parent != null)
77 parent.HandleCancelled(InternalCancel);
79 78 }
80 79
81 /// <summary>
82 /// Π‘ΠΎΠ±Ρ‹Ρ‚ΠΈΠ΅, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‰Π΅Π΅ ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
83 /// </summary>
84 /// <description>
85 /// Как ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для оповСщСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰Π΅Π³ΠΎ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π΅Π΅ слСдуСт ΠΎΡ‚ΠΌΠ΅Π½ΠΈΡ‚ΡŒ.
86 /// </description>
87 public event EventHandler Cancelled;
80 void InternalCancel() {
81 // don't try to cancel parent :)
82 Cancel(false);
83 }
88 84
89 85 /// <summary>
90 86 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ.
91 87 /// </summary>
92 88 /// <param name="result">Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния.</param>
93 89 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
94 90 public void Resolve(T result) {
95 91 lock (this) {
96 92 if (m_state == PromiseState.Cancelled)
97 93 return;
98 94 if (m_state != PromiseState.Unresolved)
99 95 throw new InvalidOperationException("The promise is already resolved");
100 96 m_result = result;
101 97 m_state = PromiseState.Resolved;
102 98 }
103 99
104 // state has been changed to rejected new handlers can't be added
105
106 foreach (var handler in m_resultHandlers)
107 InvokeHandler(handler);
108
109 /* ResultHandlerInfo handler;
110 while (FetchNextHandler(out handler))
111 InvokeHandler(handler); */
100 OnStateChanged();
112 101 }
113 102
114 103 /// <summary>
115 104 /// ВыполняСт ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, сообщая ΠΎΠ± ошибкС
116 105 /// </summary>
117 106 /// <param name="error">Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ</param>
118 107 /// <exception cref="InvalidOperationException">Π”Π°Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ</exception>
119 108 public void Reject(Exception error) {
120 109 lock (this) {
121 110 if (m_state == PromiseState.Cancelled)
122 111 return;
123 112 if (m_state != PromiseState.Unresolved)
124 113 throw new InvalidOperationException("The promise is already resolved");
125 114 m_error = error;
126 115 m_state = PromiseState.Rejected;
127 116 }
128 117
129 // state has been changed to rejected new handlers can't be added
130
131 foreach (var handler in m_resultHandlers)
132 InvokeHandler(handler);
133
134 /*ResultHandlerInfo handler;
135 while (FetchNextHandler(out handler))
136 InvokeHandler(handler);*/
118 OnStateChanged();
137 119 }
138 120
139 121 /// <summary>
140 122 /// ΠžΡ‚ΠΌΠ΅Π½ΡΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ссли это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.
141 123 /// </summary>
142 124 /// <returns><c>true</c> ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ Π±Ρ‹Π»Π° ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Π°, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹.<c>false</c> ΠΎΡ‚ΠΌΠ΅Π½Π° Π½Π΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΡƒΠΆΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ.</returns>
143 125 public bool Cancel() {
144 126 return Cancel(true);
145 127 }
146 128
129 protected virtual void OnStateChanged() {
130 switch (m_state) {
131 case PromiseState.Resolved:
132 foreach (var resultHandlerInfo in m_resultHandlers)
133 try {
134 if (resultHandlerInfo.resultHandler != null)
135 resultHandlerInfo.resultHandler(m_result);
136 } catch (Exception e) {
137 try {
138 if (resultHandlerInfo.errorHandler != null)
139 resultHandlerInfo.errorHandler(e);
140 } catch { }
141 }
142 break;
143 case PromiseState.Cancelled:
144 foreach (var cancelHandler in m_cancelHandlers)
145 cancelHandler();
146 break;
147 case PromiseState.Rejected:
148 foreach (var resultHandlerInfo in m_resultHandlers)
149 try {
150 if (resultHandlerInfo.errorHandler != null)
151 resultHandlerInfo.errorHandler(m_error);
152 } catch { }
153 break;
154 default:
155 throw new InvalidOperationException(String.Format("Promise entered an invalid state {0}", m_state));
156 }
157
158 m_resultHandlers = null;
159 m_cancelHandlers = null;
160 }
161
147 162 /// <summary>
148 163 /// ДобавляСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ событий выполнСния обСщания.
149 164 /// </summary>
150 165 /// <param name="success">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ выполнСния обСщания.
151 166 /// Π”Π°Π½Π½ΠΎΠΌΡƒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡƒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
152 167 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
153 168 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
154 169 /// <returns>Π‘Π°ΠΌΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅</returns>
155 170 public Promise<T> Then(ResultHandler<T> success, ErrorHandler error) {
156 171 if (success == null && error == null)
157 172 return this;
158 173
159 174 var medium = new Promise<T>();
160 175
161 176 var handlerInfo = new ResultHandlerInfo();
162 177
163 178 if (success != null)
164 179 handlerInfo.resultHandler = x => {
165 try {
166 180 success(x);
167 181 medium.Resolve(x);
168 } catch (Exception e) {
169 medium.Reject(e);
170 }
171 182 };
172 183 else
173 handlerInfo.resultHandler = x => medium.Resolve(x);
184 handlerInfo.resultHandler = medium.Resolve;
174 185
175 186 if (error != null)
176 187 handlerInfo.errorHandler = x => {
177 188 try {
178 189 error(x);
179 190 } catch { }
180 191 medium.Reject(x);
181 192 };
182 193 else
183 handlerInfo.errorHandler = x => medium.Reject(x);
194 handlerInfo.errorHandler = medium.Reject;
184 195
185 196 AddHandler(handlerInfo);
186 197
187 198 return medium;
188 199 }
189 200
190 201 public Promise<T> Then(ResultHandler<T> success) {
191 202 return Then(success, null);
192 203 }
193 204
194 205 public Promise<T> Error(ErrorHandler error) {
195 206 return Then(null, error);
196 207 }
197 208
198 209 public Promise<T> Anyway(Action handler) {
199 210 if (handler == null)
200 211 return this;
201 212
202 213 var medium = new Promise<T>();
203 214
204 215 AddHandler(new ResultHandlerInfo {
205 216 resultHandler = x => {
217 // to avoid handler being called multiple times we handle exception by ourselfs
206 218 try {
207 219 handler();
208 220 medium.Resolve(x);
209 221 } catch (Exception e) {
210 222 medium.Reject(e);
211 223 }
212 224 },
213 225 errorHandler = x => {
214 226 try {
215 227 handler();
216 228 } catch { }
217 229 medium.Reject(x);
218 230 }
219 231 });
220 232
221 233 return medium;
222 234 }
223 235
224 236 /// <summary>
225 237 /// ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.
226 238 /// </summary>
227 239 /// <typeparam name="TNew">Новый Ρ‚ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.</typeparam>
228 240 /// <param name="mapper">ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΊ Π½ΠΎΠ²ΠΎΠΌΡƒ Ρ‚ΠΈΠΏΡƒ.</param>
229 241 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
230 242 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
231 243 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ исходного обСщания.</returns>
232 244 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler error) {
233 245 if (mapper == null)
234 246 throw new ArgumentNullException("mapper");
235 247
236 248 // создаСм ΠΏΡ€ΠΈΡ†Π΅ΠΏΠ»Π΅Π½Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅
237 Promise<TNew> chained = new Promise<TNew>();
249 var chained = new Promise<TNew>();
238 250
239 251 AddHandler(new ResultHandlerInfo() {
240 resultHandler = delegate(T result) {
241 try {
242 // Ссли ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ выдаст ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ сработаСт reject сцСплСнного deferred
243 chained.Resolve(mapper(result));
244 } catch (Exception e) {
245 chained.Reject(e);
246 }
247 },
252 resultHandler = result => chained.Resolve(mapper(result)),
248 253 errorHandler = delegate(Exception e) {
249 254 if (error != null)
255 try {
250 256 error(e);
257 } catch { }
251 258 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
252 259 chained.Reject(e);
253 260 }
254 261 });
255 262
256 263 return chained;
257 264 }
258 265
259 266 public Promise<TNew> Map<TNew>(ResultMapper<T, TNew> mapper) {
260 267 return Map(mapper, null);
261 268 }
262 269
263 270 /// <summary>
264 271 /// БцСпляСт нСсколько аснхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Указанная асинхронная опСрация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½Π° послС
265 272 /// выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ
266 273 /// Π½ΠΎΠ²ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.
267 274 /// </summary>
268 275 /// <typeparam name="TNew">Π’ΠΈΠΏ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</typeparam>
269 276 /// <param name="chained">Асинхронная опСрация, которая Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ послС выполнСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.</param>
270 277 /// <param name="error">ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ошибки. Π”Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚
271 278 /// ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ возникшСС ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Ρ‚Π΅ΠΊΡƒΠ΅Ρ‰ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</param>
272 279 /// <returns>НовоС ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΡŽ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ аснхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.</returns>
273 280 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained, ErrorHandler error) {
274 281
275 282 // ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ связывания Π΅Ρ‰Π΅ Π½Π΅ Π½Π°Ρ‡Π°Ρ‚Π° асинхронная опСрация, поэтому Π½ΡƒΠΆΠ½ΠΎ
276 283 // ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ посрСдника, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΠ΄Π²Ρ‹Π·ΡΠ²Π°Ρ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ.
277 284 // ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Π°Ρ асинхронная опСрация, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ посрСднику, Ρ‡Ρ‚ΠΎΠ±Ρ‹
278 285 // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π½Π΅Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹.
279 Promise<TNew> medium = new Promise<TNew>();
286 var medium = new Promise<TNew>(this, true);
280 287
281 AddHandler(new ResultHandlerInfo() {
288 AddHandler(new ResultHandlerInfo {
282 289 resultHandler = delegate(T result) {
283 try {
284 chained(result).Then(
285 x => medium.Resolve(x),
286 e => medium.Reject(e)
290 if (medium.State == PromiseState.Cancelled)
291 return;
292
293 var promise = chained(result);
294
295 // notify chained operation that it's not needed
296 medium.Cancelled(() => promise.Cancel());
297 promise.Then(
298 medium.Resolve,
299 medium.Reject
287 300 );
288 } catch (Exception e) {
289 // Ссли сцСплСнноС дСйствиС Π²Ρ‹Π΄Π°Π»ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ вмСсто обСщания, Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
290 medium.Reject(e);
291 }
292 301 },
293 302 errorHandler = delegate(Exception e) {
294 303 if (error != null)
295 304 error(e);
296 305 // Π² случаС ошибки Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ дальшС ΠΏΠΎ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅
297 306 medium.Reject(e);
298 307 }
299 308 });
300 309
301 310 return medium;
302 311 }
303 312
304 313 public Promise<TNew> Chain<TNew>(ChainedOperation<T, TNew> chained) {
305 314 return Chain(chained, null);
306 315 }
307 316
317 public Promise<T> Cancelled(Action handler) {
318 if (handler == null)
319 return this;
320 lock (m_lock) {
321 if (m_state == PromiseState.Unresolved)
322 m_cancelHandlers.AddLast(handler);
323 else if (m_state == PromiseState.Cancelled)
324 handler();
325 }
326 return this;
327 }
328
329 public void HandleCancelled(Action handler) {
330 Cancelled(handler);
331 }
332
308 333 /// <summary>
309 334 /// ДоТидаСтся ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ обСщания ΠΈ Π² случаС успСха, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚
310 335 /// Π΅Π³ΠΎ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС бросаСт ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
311 336 /// </summary>
312 337 /// <remarks>
313 338 /// <para>
314 339 /// Если ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ обСщания Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Ρ€Π²Π°Π½ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚Ρƒ, это Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚,
315 340 /// Ρ‡Ρ‚ΠΎ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±Ρ‹Π»ΠΎ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ΠΎ ΠΈΠ»ΠΈ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π² этом Ρ€ΠΎΠ΄Π΅, это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ
316 341 /// ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΅Π³ΠΎ Π½Π΅ доТдались, ΠΎΠ΄Π½Π°ΠΊΠΎ всС зарСгистрированныС
317 342 /// ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΈ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ‹Π·Π²Π°Π½Ρ‹, ΠΊΠΎΠ³Π΄Π°
318 343 /// ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ.
319 344 /// </para>
320 345 /// <para>
321 346 /// Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π²ΠΏΠΎΠ»Π½Π΅ ΠΎΠΏΡ€Π°Π²Π΄Π°Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π°ΠΉΠΌΠ°ΡƒΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‚Π΅Ρ‡ΡŒ
322 347 /// Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π½Π°Ρ‡Π°Π»Π°ΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ², ΠΈ
323 348 /// ΠΊ Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΡ‚ΠΎΡΡ‚ΡŒ Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠΉ ΠΈ Π΅Π³ΠΎ
324 349 /// ΠΎΡ‚ΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΏΡ€ΠΎΠ³Π½ΠΎΠ·ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠΌΡƒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρƒ.
325 350 /// </para>
326 351 /// </remarks>
327 352 /// <param name="timeout">ВрСмя оТидания</param>
328 353 /// <returns>Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния обСщания</returns>
329 354 public T Join(int timeout) {
330 ManualResetEvent evt = new ManualResetEvent(false);
355 var evt = new ManualResetEvent(false);
331 356 Anyway(() => evt.Set());
357 Cancelled(() => evt.Set());
332 358
333 359 if (!evt.WaitOne(timeout, true))
334 360 throw new TimeoutException();
335 361
336 if (m_error != null)
362 switch (State) {
363 case PromiseState.Resolved:
364 return m_result;
365 case PromiseState.Cancelled:
366 throw new OperationCanceledException();
367 case PromiseState.Rejected:
337 368 throw new TargetInvocationException(m_error);
338 else
339 return m_result;
369 default:
370 throw new ApplicationException(String.Format("Invalid promise state {0}", State));
371 }
340 372 }
341 373
342 374 public T Join() {
343 375 return Join(Timeout.Infinite);
344 376 }
345 377
346 /// <summary>
347 /// Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ обСщания ΠΈ ΠΊΠΎΠ³Π΄Π°
348 /// ΠΈΡ… большС Π½Π΅ ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ - ставит состояниС "Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ".
349 /// </summary>
350 /// <param name="handler">Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ ΠΎΠ± ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ΅</param>
351 /// <returns>ΠŸΡ€ΠΈΠ·Π½Π°ΠΊ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π΅Ρ‰Π΅ ΠΎΡΡ‚Π°Π»ΠΈΡΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ</returns>
352 bool FetchNextHandler(out ResultHandlerInfo handler) {
353 handler = default(ResultHandlerInfo);
354
355 lock (this) {
356 Debug.Assert(m_state != PromiseState.Unresolved);
357
358 if (m_resultHandlers.Count > 0) {
359 handler = m_resultHandlers.First.Value;
360 m_resultHandlers.RemoveFirst();
361 return true;
362 } else {
363 return false;
364 }
365 }
366 }
367
368 378 void AddHandler(ResultHandlerInfo handler) {
369 379 bool invokeRequired = false;
370 380
371 lock (this) {
372 if (m_state == PromiseState.Unresolved)
381 lock (m_lock) {
382 m_childrenCount++;
383 if (m_state == PromiseState.Unresolved) {
373 384 m_resultHandlers.AddLast(handler);
374 else
385 } else
375 386 invokeRequired = true;
376 387 }
377 388
378 389 // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сам ΠΎΠ±ΡŠΠ΅ΠΊΡ‚
379 390 if (invokeRequired)
380 391 InvokeHandler(handler);
381 392 }
382 393
383 394 void InvokeHandler(ResultHandlerInfo handler) {
384 if (m_error == null) {
395 switch (m_state) {
396 case PromiseState.Resolved:
385 397 try {
386 398 if (handler.resultHandler != null)
387 399 handler.resultHandler(m_result);
400 } catch (Exception e) {
401 try {
402 if (handler.errorHandler != null)
403 handler.errorHandler(e);
388 404 } catch { }
389 405 }
390
391 if (m_error != null) {
406 break;
407 case PromiseState.Rejected:
392 408 try {
393 409 if (handler.errorHandler != null)
394 410 handler.errorHandler(m_error);
395 411 } catch { }
412 break;
413 default:
414 // do nothing
415 return;
396 416 }
397 417 }
398 418
399 419
400 420
401 421 public bool IsExclusive {
402 422 get {
403 423 lock (m_lock) {
404 424 return m_childrenCount <= 1;
405 425 }
406 426 }
407 427 }
408 428
409 429 public PromiseState State {
410 430 get {
411 431 lock (m_lock) {
412 432 return m_state;
413 433 }
414 434 }
415 435 }
416 436
417 437 public bool Cancel(bool dependencies) {
418 438 bool result;
419 439
420 440 lock (m_lock) {
421 441 if (m_state == PromiseState.Unresolved) {
422 442 m_state = PromiseState.Cancelled;
423 443 result = true;
424 444 } else {
425 445 result = false;
426 446 }
427 447 }
428 448
429 if (dependencies && m_parent != null && m_parent.IsExclusive) {
430 // TODO syncronize IsExclusive, AddHandler, Cancel (maybe CancelExclusive)
431 m_parent.Cancel(true);
432 }
449 if (result)
450 OnStateChanged();
433 451
434 if (result) {
435 // state has been changed to cancelled, new handlers can't be added
436 foreach (var handler in m_cancelHandlers)
437 handler();
452 if (dependencies && m_parent != null && m_parent.IsExclusive) {
453 m_parent.Cancel(true);
438 454 }
439 455
440 456 return result;
441 457 }
442 458 }
443 459 }
@@ -1,113 +1,112
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Threading;
6 6
7 7 namespace Implab
8 8 {
9 9 /// <summary>
10 10 /// This class allows to interact with asyncronuos task.
11 11 /// </summary>
12 12 /// <remarks>
13 13 /// Members of this object are thread safe.
14 14 /// </remarks>
15 15 class TaskController
16 16 {
17 object m_lock;
17 readonly object m_lock;
18 18 string m_message;
19 bool m_cancelled;
20 19
21 20 float m_current;
22 21 float m_max;
23 22
24 23 public event EventHandler<ValueEventArgs<string>> MessageUpdated;
25 24 public event EventHandler<ValueEventArgs<float>> ProgressUpdated;
26 25 public event EventHandler<ProgressInitEventArgs> ProgressInit;
27 26
28 27 public TaskController()
29 28 {
30 29 m_lock = new Object();
31 30 }
32 31
33 32 public string Message
34 33 {
35 34 get
36 35 {
37 36 lock (m_lock)
38 37 return m_message;
39 38 }
40 39 set
41 40 {
42 41 lock (m_lock)
43 42 {
44 43 m_message = value;
45 44 OnMessageUpdated();
46 45 }
47 46 }
48 47 }
49 48
50 49 public float CurrentProgress
51 50 {
52 51 get
53 52 {
54 53 lock (m_lock)
55 54 return m_current;
56 55 }
57 56 set
58 57 {
59 58 lock (m_lock)
60 59 {
61 60 var prev = m_current;
62 61 m_current = value;
63 62 if (m_current >= m_max)
64 63 m_current = m_max;
65 64 if (m_current != prev)
66 65 OnProgressUpdated();
67 66 }
68 67 }
69 68 }
70 69
71 70 public void InitProgress(float current, float max, string message)
72 71 {
73 72 if (max < 0)
74 73 throw new ArgumentOutOfRangeException("max");
75 74 if (current < 0 || current > max)
76 75 throw new ArgumentOutOfRangeException("current");
77 76
78 77 lock(m_lock) {
79 78 m_current = current;
80 79 m_max = max;
81 80 m_message = message;
82 81 OnProgressInit();
83 82 }
84 83 }
85 84
86 85 protected virtual void OnMessageUpdated()
87 86 {
88 87 var temp = MessageUpdated;
89 88 if (temp != null)
90 89 {
91 90 temp(this, new ValueEventArgs<string>(m_message));
92 91 }
93 92 }
94 93
95 94 protected virtual void OnProgressUpdated()
96 95 {
97 96 var temp = ProgressUpdated;
98 97 if (temp != null)
99 98 {
100 99 temp(this,new ValueEventArgs<float>(m_current));
101 100 }
102 101 }
103 102
104 103 protected virtual void OnProgressInit()
105 104 {
106 105 var temp = ProgressInit;
107 106 if (temp != null)
108 107 {
109 108 temp(this, new ProgressInitEventArgs(m_current,m_max, m_message));
110 109 }
111 110 }
112 111 }
113 112 }
General Comments 0
You need to be logged in to leave comments. Login now