首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ManagedThreadID与操作系统ThreadID的关系

ManagedThreadID与操作系统ThreadID的关系
EN

Stack Overflow用户
提问于 2009-08-14 20:13:28
回答 4查看 5.6K关注 0票数 7

我正在处理一个多线程的C#窗口应用程序,它经常调用一个本机dll。这些都是阻塞呼叫,有时会持续相当长的时间。

在某些情况下,我想从主线程取消对某些工作线程的这些阻塞调用,我使用的本机API为此提供了一个函数:

代码语言:javascript
复制
HRESULT CancelBlockingCall(DWORD ThreadID)

虽然CancelBlockingCall()的文档不是很清楚,但我认为我需要为阻塞调用的OS级线程传递ThreadID。基于从CancelBlockingCall()获得的返回代码,我意识到Thread.ManagedThreadID不是我所需要的。我在msdn (见注)上发现了以下内容

操作系统ThreadId与托管线程没有固定关系,因为非托管主机可以控制托管线程和非托管线程之间的关系。具体来说,复杂的主机可以使用CLR宿主API对同一个操作系统线程调度许多托管线程,或者在不同的操作系统线程之间移动托管线程。

这是否意味着我无法为托管线程正确调用CancelBlockingCall()?是否不可能确定托管线程当前正在执行的操作系统级别线程的ThreadId?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-08-14 20:27:37

这是否意味着我无法为托管线程正确调用CancelBlockingCall()?是否不可能确定托管线程当前正在执行的操作系统级别线程的ThreadId?

正如Aidan所说,您可以使用GetCurrentThreadID API来获取OS线程ID。

要在托管线程中跟踪它,可以将API调用包装在存储OS线程ID的类中,以便以后可以停止它:

代码语言:javascript
复制
public class APITask
{
    private uint _osThreadId;

    public void Run()
    {
        _osThreadId = GetCurrentThreadID();
        API.RunBlockingMethod();
    }

    public void Cancel()
    {
        API.CancelBlockingCall(_osThreadId);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2009-08-15 11:28:15

正如其他人所提到的,在调用阻塞的本机函数并在某个地方注册id之前,您可以尝试调用p/ GetCurrentThreadId,但这是一个定时炸弹--总有一天,您的托管线程会被抢占,并在两个p/调用调用之间重新调度到不同的OS级线程。我建议的唯一可靠方法是编写一个很小的非托管代理dll,它将首先调用GetCurrentThreadId (将其写入托管代码可见的某个地方),然后调用您的原生阻塞函数。对托管代码(而不是out IntPtr )的回调也可能有效;当堆栈上有非托管帧时,CLR很难重新调度线程。

编辑:显然,并不是第一个出现这样问题的人:System.Threading.Thread中有两种方便的方法,一种是用来解除我提到的定时炸弹,另一种是p/invoke GetCurrentThreadId()Thread.BeginThreadAffinity()Thread.EndThreadAffinity()。CLR主机不会在这些调用之间将托管线程重新调度到不同的本机线程。但是,您的代码需要在较高的信任级别上运行才能调用这些方法。

票数 14
EN

Stack Overflow用户

发布于 2009-08-14 20:17:49

您可以尝试调用P/ GetCurrentThreadID API。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1279950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档