##// END OF EJS Templates
fix
cin -
r239:eedf4d834e67 v2
parent child
Show More
@@ -1,147 +1,147
1 1 using Implab.Parallels;
2 2 using System;
3 3 using System.Collections.Generic;
4 4 using System.Linq;
5 5 using System.Text;
6 6 using System.Threading;
7 7 using System.Threading.Tasks;
8 8 using System.Windows.Forms;
9 9
10 10 namespace Implab.Diagnostics.Interactive
11 11 {
12 12 public class InteractiveListener: ListenerBase
13 13 {
14 14 TraceForm m_form;
15 15
16 16 SynchronizationContext m_syncGuiThread;
17 17 readonly Promise m_guiStarted = new Promise();
18 18
19 19 readonly IPromise m_guiFinished;
20 20
21 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
21 readonly SimpleAsyncQueue<TraceViewItem> m_queue = new SimpleAsyncQueue<TraceViewItem>();
22 22 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
23 23
24 24 int m_queueLength;
25 25 bool m_exitPending;
26 26
27 27 readonly object m_pauseLock = new object();
28 28 bool m_paused;
29 29 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
30 30
31 31 public InteractiveListener() {
32 32 m_guiFinished = RunGuiThread();
33 33 AsyncPool.RunThread(QueueThread);
34 34
35 35 m_guiStarted.Join();
36 36 }
37 37
38 38 void GuiThread() {
39 39 m_form = new TraceForm(); // will create SynchronizationContext
40 40
41 41 m_form.PauseEvents += (s,a) => Pause();
42 42 m_form.ResumeEvents += (s, a) => Resume();
43 43
44 44 m_syncGuiThread = SynchronizationContext.Current;
45 45 m_guiStarted.Resolve();
46 46 Application.Run();
47 47 }
48 48
49 49 void QueueThread() {
50 50 while (!m_exitPending) {
51 51 if (m_paused)
52 52 m_pauseEvent.WaitOne();
53 53
54 54 TraceViewItem item;
55 55 if (m_queue.TryDequeue(out item)) {
56 56 Interlocked.Decrement(ref m_queueLength);
57 57
58 58 m_syncGuiThread.Post(x => m_form.AddTraceEvent(item),null);
59 59 } else {
60 60 m_queueEvent.WaitOne();
61 61 }
62 62 }
63 63 }
64 64
65 65 public IPromise RunGuiThread() {
66 66 var p = new Promise();
67 67
68 68 var caller = TraceContext.Instance.CurrentOperation;
69 69
70 70 var worker = new Thread(() => {
71 71 TraceContext.Instance.EnterLogicalOperation(caller, false);
72 72 try {
73 73 Application.OleRequired();
74 74 GuiThread();
75 75 p.Resolve();
76 76 } catch (Exception e) {
77 77 p.Reject(e);
78 78 } finally {
79 79 TraceContext.Instance.Leave();
80 80 }
81 81 });
82 82 worker.SetApartmentState(ApartmentState.STA);
83 83 worker.IsBackground = true;
84 84 worker.Name = string.Format("{0} GUI Thread", nameof(InteractiveListener));
85 85 worker.Start();
86 86
87 87 return p;
88 88 }
89 89
90 90 public void Pause() {
91 91 // for consistency we need to set this properties atomically
92 92 lock (m_pauseLock) {
93 93 m_pauseEvent.Reset();
94 94 m_paused = true;
95 95 }
96 96 }
97 97
98 98 public void Resume() {
99 99 // for consistency we need to set this properties atomically
100 100 lock (m_pauseLock) {
101 101 m_paused = false;
102 102 m_pauseEvent.Set();
103 103 }
104 104 }
105 105
106 106 void Enqueue(TraceViewItem item) {
107 107 m_queue.Enqueue(item);
108 108 if (Interlocked.Increment(ref m_queueLength) == 1)
109 109 m_queueEvent.Set();
110 110 }
111 111
112 112 public void ShowForm() {
113 113 m_syncGuiThread.Post(x => m_form.Show(), null);
114 114 }
115 115
116 116 public void HideForm() {
117 117 m_syncGuiThread.Post(x => m_form.Hide(), null);
118 118 }
119 119
120 120 void Terminate() {
121 121 m_exitPending = true;
122 122 Resume();
123 123 m_syncGuiThread.Post(x => Application.ExitThread(), null);
124 124 }
125 125
126 126 protected override void Dispose(bool disposing) {
127 127 if (disposing) {
128 128 Terminate();
129 129 m_guiFinished.Join();
130 130 }
131 131 base.Dispose(disposing);
132 132 }
133 133
134 134 public override void Write(LogEventArgs args, object entry) {
135 135 var item = new TraceViewItem {
136 136 Indent = args.Operation.Level,
137 137 Message = entry.ToString(),
138 138 Thread = args.ThreadId,
139 139 Channel = args.Channel.ToString(),
140 140 Timestamp = Environment.TickCount,
141 141 TimeDelta = args.OperationTimeOffset
142 142 };
143 143
144 144 Enqueue(item);
145 145 }
146 146 }
147 147 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

ok, latest stable version should be in default

You need to be logged in to leave comments. Login now