annotate Implab.Fx/StaApartment.cs @ 210:5dc21f6a3222 v2

Code review for RunnableComponent Added StaApartment class based on System.Windows.Forms.Application message loop
author cin
date Mon, 20 Mar 2017 17:44:18 +0300
parents
children 3eb3255d8cc5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
210
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
1 using Implab.Components;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
2 using Implab.Diagnostics;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
3 using Implab.Parallels;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
4 using System;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
5 using System.Collections.Generic;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
6 using System.Linq;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
7 using System.Text;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
8 using System.Threading;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
9 using System.Threading.Tasks;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
10 using System.Windows.Forms;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
11
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
12 namespace Implab.Fx {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
13 public class StaApartment : RunnableComponent {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
14 readonly Thread m_worker;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
15 SynchronizationContext m_syncContext;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
16 readonly Promise m_threadStarted;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
17 readonly Promise m_threadTerminated;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
18
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
19 public StaApartment() : base(true) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
20 m_threadStarted = new Promise();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
21 m_threadTerminated = new Promise();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
22
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
23 m_worker = new Thread(WorkerEntry);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
24 m_worker.SetApartmentState(ApartmentState.STA);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
25 m_worker.IsBackground = true;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
26 m_worker.Name = "STA managed aparment";
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
27 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
28
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
29 public SynchronizationContext SyncContext {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
30 get {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
31 if (m_syncContext == null)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
32 throw new InvalidOperationException();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
33 return m_syncContext;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
34 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
35 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
36
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
37 public IPromise Invoke(Action<ICancellationToken> action) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
38 Safe.ArgumentNotNull(action, "action");
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
39
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
40 if (m_syncContext == null)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
41 throw new InvalidOperationException();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
42 var p = new Promise();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
43 var lop = TraceContext.Instance.CurrentOperation;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
44
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
45 m_syncContext.Post(x => {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
46 TraceContext.Instance.EnterLogicalOperation(lop, false);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
47 try {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
48 if (p.CancelOperationIfRequested())
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
49 return;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
50
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
51 action(p);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
52 p.Resolve();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
53 } catch (Exception e) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
54 p.Reject(e);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
55 } finally {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
56 TraceContext.Instance.Leave();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
57 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
58 }, null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
59
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
60 return p;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
61 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
62
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
63 public IPromise<T> Invoke<T>(Func<ICancellationToken, T> action) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
64 Safe.ArgumentNotNull(action, "action");
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
65
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
66 if (m_syncContext == null)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
67 throw new InvalidOperationException();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
68 var p = new Promise<T>();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
69 var lop = TraceContext.Instance.CurrentOperation;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
70
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
71 m_syncContext.Post(x => {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
72 TraceContext.Instance.EnterLogicalOperation(lop, false);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
73 try {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
74 if (p.CancelOperationIfRequested())
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
75 return;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
76 p.Resolve(action(p));
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
77 } catch (Exception e) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
78 p.Reject(e);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
79 } finally {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
80 TraceContext.Instance.Leave();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
81 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
82 }, null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
83
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
84 return p;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
85 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
86
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
87 public IPromise Invoke(Action action) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
88 Safe.ArgumentNotNull(action, "action");
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
89
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
90 if (m_syncContext == null)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
91 throw new InvalidOperationException();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
92 var p = new Promise();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
93 var lop = TraceContext.Instance.CurrentOperation;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
94
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
95 m_syncContext.Post(x => {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
96 TraceContext.Instance.EnterLogicalOperation(lop, false);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
97 try {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
98 if (p.CancelOperationIfRequested())
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
99 return;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
100 action();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
101 p.Resolve();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
102 } catch (Exception e) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
103 p.Reject(e);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
104 } finally {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
105 TraceContext.Instance.Leave();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
106 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
107 }, null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
108
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
109 return p;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
110 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
111
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
112 public IPromise<T> Invoke<T>(Func<T> action) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
113 Safe.ArgumentNotNull(action, "action");
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
114
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
115 if (m_syncContext == null)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
116 throw new InvalidOperationException();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
117 var p = new Promise<T>();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
118 var lop = TraceContext.Instance.CurrentOperation;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
119
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
120 m_syncContext.Post(x => {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
121 TraceContext.Instance.EnterLogicalOperation(lop, false);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
122 try {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
123 if (p.CancelOperationIfRequested())
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
124 return;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
125 p.Resolve(action());
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
126 } catch (Exception e) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
127 p.Reject(e);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
128 } finally {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
129 TraceContext.Instance.Leave();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
130 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
131 }, null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
132
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
133 return p;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
134 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
135
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
136
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
137 /// <summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
138 /// Starts the apartment thread
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
139 /// </summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
140 /// <returns>Promise which will be fullfiled when the syncronization
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
141 /// context will be ready to accept tasks.</returns>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
142 protected override IPromise OnStart() {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
143 m_worker.Start();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
144 return m_threadStarted;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
145 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
146
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
147 /// <summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
148 /// Posts quit message to the message loop of the apartment
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
149 /// </summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
150 /// <returns>Promise</returns>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
151 protected override IPromise OnStop() {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
152 m_syncContext.Post(x => Application.ExitThread(), null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
153 return m_threadTerminated;
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
154 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
155
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
156 void WorkerEntry() {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
157 m_syncContext = new WindowsFormsSynchronizationContext();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
158 SynchronizationContext.SetSynchronizationContext(m_syncContext);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
159
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
160 m_threadStarted.Resolve();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
161
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
162 Application.OleRequired();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
163 Application.Run();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
164
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
165 try {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
166 OnShutdown();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
167 m_threadTerminated.Resolve();
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
168 } catch(Exception err) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
169 m_threadTerminated.Reject(err);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
170 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
171 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
172
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
173 /// <summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
174 /// Called from the STA apartment after the message loop is terminated, override this
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
175 /// method to handle apartment cleanup.
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
176 /// </summary>
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
177 protected virtual void OnShutdown() {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
178 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
179
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
180 protected override void Dispose(bool disposing) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
181 if (disposing) {
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
182 if (!m_threadTerminated.IsResolved)
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
183 m_syncContext.Post(x => Application.ExitThread(), null);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
184 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
185 base.Dispose(disposing);
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
186 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
187 }
5dc21f6a3222 Code review for RunnableComponent
cin
parents:
diff changeset
188 }