如何获取传递给CancelSynchronousIO的线程句柄?

use*_*455 8 c# multithreading

以正常方式在C#中创建后台线程 -

Thread t = new Thread(....);
t.IsBackground = true;
t.Start();
etc etc
Run Code Online (Sandbox Code Playgroud)

想要CancelSynchronousIO从主线程调用取消后台线程上的阻塞IO调用.不知道如何以IntPtr的形式获取线程句柄以传递给函数:

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool CancelSynchronousIo(IntPtr threadHandle);
Run Code Online (Sandbox Code Playgroud)

似乎有各种方法来获取线程ID,但不是句柄?获取线程ID的方式似乎只在托管环境中提供了一个ID,所以没有用于PInvoke调用?我猜我错过了什么.

我是否需要执行其他PInvoke调用以获取线程句柄或者是否有更简单的方法?

小智 6

您可以这样做,但强烈不建议这样做。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern uint GetCurrentThreadId();

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr OpenThread(uint desiredAccess, bool inheritHandle, uint threadId);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr handle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CancelSynchronousIo(IntPtr threadHandle);

    static bool CancelSynchronousIo(uint threadId)
    {
        // GENERIC_WRITE, Non-inheritable
        var threadHandle = OpenThread(0x40000000, false, (uint)threadId);
        var ret = CancelSynchronousIo(threadHandle);

        CloseHandle(threadHandle);

        return ret;
    }

    static void Main(string[] args)
    {
        uint threadId = 0;

        using (var threadStarted = new AutoResetEvent(false))
        {
            var thread = new Thread(() =>
            {
                try
                {
                    Thread.BeginThreadAffinity();
                    threadId = GetCurrentThreadId();

                    threadStarted.Set();

                    // will throws System.OperationCanceledException
                    Console.ReadLine();
                }
                finally
                {
                    Thread.EndThreadAffinity();
                }
            });

            thread.Start();

            threadStarted.WaitOne();
        }

        Debugger.Break();

        CancelSynchronousIo(threadId);
    }
}
Run Code Online (Sandbox Code Playgroud)