Mercurial > pub > ImplabNet
comparison Implab.Diagnostics.Interactive/InteractiveListener.cs @ 47:b181f7bcb259 interactive logger
refactoring, interactive tarce log almost complete
author | cin |
---|---|
date | Thu, 17 Apr 2014 18:49:36 +0400 |
parents | |
children | d9d794b61bb9 |
comparison
equal
deleted
inserted
replaced
46:9ce97b262a7a | 47:b181f7bcb259 |
---|---|
1 using Implab.Parallels; | |
2 using System; | |
3 using System.Collections.Generic; | |
4 using System.Linq; | |
5 using System.Text; | |
6 using System.Threading; | |
7 using System.Threading.Tasks; | |
8 using System.Windows.Forms; | |
9 | |
10 namespace Implab.Diagnostics.Interactive | |
11 { | |
12 public class InteractiveListener: Disposable | |
13 { | |
14 TraceForm m_form; | |
15 | |
16 SynchronizationContext m_syncGuiThread; | |
17 | |
18 readonly IPromiseBase m_guiFinished; | |
19 readonly Promise<object> m_guiStarted = new Promise<object>(); | |
20 | |
21 readonly IPromiseBase m_workerFinished = new Promise<object>(); | |
22 | |
23 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>(); | |
24 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false); | |
25 | |
26 int m_queueLength; | |
27 bool m_exitPending; | |
28 | |
29 readonly object m_pauseLock = new object(); | |
30 bool m_paused; | |
31 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true); | |
32 | |
33 public InteractiveListener() { | |
34 m_guiFinished = AsyncPool.InvokeNewThread(() => { | |
35 GuiThread(); | |
36 return 0; | |
37 }); | |
38 | |
39 m_guiStarted.Join(); | |
40 } | |
41 | |
42 void GuiThread() { | |
43 m_form = new TraceForm(); // will create SynchronizationContext | |
44 m_syncGuiThread = SynchronizationContext.Current; | |
45 m_guiStarted.Resolve(); | |
46 Application.Run(); | |
47 } | |
48 | |
49 void QueueThread() { | |
50 while (!m_exitPending) { | |
51 if (m_paused) | |
52 m_pauseEvent.WaitOne(); | |
53 | |
54 TraceViewItem item; | |
55 if (m_queue.TryDequeue(out item)) { | |
56 Interlocked.Decrement(ref m_queueLength); | |
57 | |
58 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null); | |
59 } else { | |
60 m_queueEvent.WaitOne(); | |
61 } | |
62 } | |
63 } | |
64 | |
65 public void Pause() { | |
66 // for consistency we need to set this properties atomically | |
67 lock (m_pauseLock) { | |
68 m_pauseEvent.Reset(); | |
69 m_paused = true; | |
70 } | |
71 } | |
72 | |
73 public void Resume() { | |
74 // for consistency we need to set this properties atomically | |
75 lock (m_pauseLock) { | |
76 m_paused = false; | |
77 m_pauseEvent.Set(); | |
78 } | |
79 } | |
80 | |
81 void Enqueue(TraceViewItem item) { | |
82 m_queue.Enqueue(item); | |
83 if (Interlocked.Increment(ref m_queueLength) == 1) | |
84 m_queueEvent.Set(); | |
85 } | |
86 | |
87 public void ShowForm() { | |
88 m_syncGuiThread.Post(x => m_form.Show(), null); | |
89 } | |
90 | |
91 public void HideForm() { | |
92 m_syncGuiThread.Post(x => m_form.Hide(), null); | |
93 } | |
94 | |
95 void Terminate() { | |
96 m_syncGuiThread.Post(x => Application.ExitThread(), null); | |
97 } | |
98 | |
99 protected override void Dispose(bool disposing) { | |
100 if (disposing) { | |
101 Terminate(); | |
102 m_guiFinished.Join(); | |
103 } | |
104 base.Dispose(disposing); | |
105 } | |
106 } | |
107 } |