/
MtaThread.cs
93 lines (83 loc) · 2.21 KB
/
MtaThread.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using AvalonStudio.Extensibility.Threading;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Mono.Debugging.Win32
{
public static class MtaThread
{
static readonly AutoResetEvent wordDoneEvent = new AutoResetEvent(false);
static Action workDelegate;
static readonly object workLock = new object();
static Thread workThread;
static Exception workError;
static readonly object threadLock = new object();
public static Thread MainThread {get; set;}
public static R Run<R> (Func<R> ts, int timeout = 15000)
{
if (Thread.CurrentThread == MainThread) {
return ts ();
}
R res = default (R);
Run (delegate {
res = ts ();
}, timeout);
return res;
}
public static void Run(Action ts, int timeout = 25000)
{
if (Thread.CurrentThread == MainThread) {
ts ();
return;
}
lock (workLock) {
lock (threadLock) {
workDelegate = ts;
workError = null;
if (workThread == null) {
workThread = new Thread (MtaRunner);
MainThread = workThread;
workThread.Name = "Win32 Debugger MTA Thread";
if (AvalonStudio.Platforms.Platform.PlatformIdentifier == AvalonStudio.Platforms.PlatformID.Win32NT)
{
workThread.SetApartmentState (ApartmentState.MTA);
}
//workThread.IsBackground = true;
workThread.Start ();
} else
// Awaken the existing thread
Monitor.Pulse (threadLock);
}
if (!wordDoneEvent.WaitOne (timeout)) {
//workThread.Abort ();
throw new Exception ("Debugger operation timeout on MTA thread.");
}
}
if (workError != null)
throw workError;
}
static void MtaRunner ()
{
try {
lock (threadLock) {
do {
try {
workDelegate ();
} catch (ThreadAbortException) {
return;
} catch (Exception ex) {
workError = ex;
} finally {
workDelegate = null;
}
wordDoneEvent.Set ();
} while (Monitor.Wait (threadLock, 60000));
}
} catch {
//Just in case if we abort just in moment when it leaves workDelegate ();
} finally {
workThread = null;
}
}
}
}