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