-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAwaitThread.cs
More file actions
92 lines (77 loc) · 2.92 KB
/
AwaitThread.cs
File metadata and controls
92 lines (77 loc) · 2.92 KB
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
// Code sample: Creating Task from System.Threading.Thread to use with await
// Author: MSDN.WhiteKnight
// Idea: VladD
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
namespace ConsoleApp1
{
public class MyWaitHandle : WaitHandle
{
public MyWaitHandle(Microsoft.Win32.SafeHandles.SafeWaitHandle swh) : base()
{
this.SafeWaitHandle = swh;
}
}
class Program
{
static void ThreadProc()
{
Console.WriteLine("Hello");
Thread.Sleep(2500);
Console.WriteLine("Goodbye");
}
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200),
SYNCHRONIZE = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle,uint dwThreadId);
public static Task<object> GetTaskFromThread(Thread th)
{
MethodInfo mi = typeof(Thread).GetMethod("GetNativeHandle", BindingFlags.NonPublic |
BindingFlags.Instance);
object thh = mi.Invoke(th, new object[0]);
FieldInfo fi = thh.GetType().GetField("m_ptr", BindingFlags.NonPublic | BindingFlags.Instance);
IntPtr clrhandle = (IntPtr)fi.GetValue(thh);
uint nativeId = (uint)Marshal.ReadInt32(clrhandle, (IntPtr.Size == 8) ? 0x022C : 0x0160); //hack (Source: https://stackoverflow.com/a/46791587/8674428)
IntPtr handle = OpenThread(ThreadAccess.SYNCHRONIZE, false, nativeId);
var swh = new Microsoft.Win32.SafeHandles.SafeWaitHandle(handle, true);
MyWaitHandle wh = new MyWaitHandle(swh);
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
WaitOrTimerCallback cb = (a, b) =>
{
tcs.TrySetResult(null);
};
ThreadPool.RegisterWaitForSingleObject(wh, cb, null, 999999, true);
return tcs.Task;
}
static void Main(string[] args)
{
AsyncMain().Wait();
Console.ReadKey();
}
static async Task AsyncMain()
{
Thread th = new Thread(ThreadProc);
th.Start();
Console.WriteLine("Thread started");
await GetTaskFromThread(th);
Console.WriteLine("Thread finished");
}
}
}