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