C# 线程——《CLR via C#(第四版)》

Posted XML火柴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 线程——《CLR via C#(第四版)》相关的知识,希望对你有一定的参考价值。

  • 线程内核对象(thread kernel object)
    OS为系统中创建的每个线程都分配并初始化这种数据结构之一。数据结构包含一组对线程进行描述的属性。数据结构还包含所谓的线程上下文(thread context)。上下文是包含CPU寄存器集合的内存块。对于x86,x64和ARM CPU架构,线程上下文分别使用约700,1240和350字节的内存。
  • 线程环境块(thread environment block,TEB)
    TEB是在用户模式(应用程序代码能快速访问的地址空间)中分配和初始化的内存块。TEB耗用一个内存页(x86,x64和ARM CPU是4KB)。TEB包含线程的异常处理链首(head)。线程进入的每个try块都在链首插入一个节点(node);线程退出try块时从链中删除该节点。此外,TEB还包含线程的“线程本地存储”数据,以及由GDI(Graphics Device Interface,图形设备接口)和OpenGL图形使用的一些数据结构。
  • 用户模式栈(user-mode stack)
    用户模式栈存储传给方法的的局部变量和实参。它还包含一个地址:指出当前方法返回时,线程应该从什么地方接着执行。Windows默认为每个线程的用户模式分配1MB内存。更具体地说,Windows只是保留1MB地址空间,在线程实际需要时才会提交(调拨)物理内存。
  • 内核模式栈(kernel-mode stack)
    应用程序代码箱操作系统中的内核模式函数传递参数时,还会使用内核模式栈。出于对安全的考虑,针对从用户模式的代码传给内核的任何实参,Windows都会把它们从线程的用户模式栈复制到献策很难过的内核模式栈。一经复制,内核就可验证实参的值。由于应用程序代码不能访问内核模式栈,所以应用程序无法更改已验证后的实参值。OS内核代码开始处理复制的值。除此之外,内核会调用它自己内部的方法,并利用内核模式栈传递它自己的实参、存储函数的局部变量以及存储返回地址。在32为Windows上运行,内核模式大小是12KB,64位是24KB。
  • DLL线程连接(attach)和线程分离(detach)通知
    Windows的一个策略是,任何时候在进程中创建线程,都会调用进程中加载的所有非托管DLL的DllMain方法,并向该方法传递DLL_THREAD_ATTACH标志。类似地,任何时候线程终止,都会调用进程中的所有非托管DLL的DllMain方法,并向该方法传递DLL_THREAD_DATACH标志。有的DLL需要获取这些通知,才能为进程中创建/销毁的每个线程执行特殊的初始化或(资源)清理操作。例如,C-Runtime库DLL会分配一些线程本地存储状态。线程使用C-Runtime库中包含的函数时需要用到折现状态。

接下来看一个函数:
DisableThreadLibraryCalls function

Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the specified dynamic-link library (DLL). This can reduce the size of the working set for some applications.

Syntax

C++

BOOL DisableThreadLibraryCalls(
  HMODULE hLibModule
);

Parameters

A handle to the DLL module for which the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications are to be disabled. The LoadLibrary, LoadLibraryEx, or GetModuleHandle function returns this handle. Note that you cannot call GetModuleHandle with NULL because this returns the base address of the executable image, not the DLL image.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. The DisableThreadLibraryCalls function fails if the DLL specified by hModule has active static thread local storage, or if hModule is an invalid module handle. To get extended error information, call GetLastError.

Remarks

The DisableThreadLibraryCalls function lets a DLL disable the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls. This can be a useful optimization for multithreaded applications that have many DLLs, frequently create and delete threads, and whose DLLs do not need these thread-level notifications of attachment/detachment. A remote procedure call (RPC) server application is an example of such an application. In these sorts of applications, DLL initialization routines often remain in memory to service DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications. By disabling the notifications, the DLL initialization code is not paged in because a thread is created or deleted, thus reducing the size of the application’s working code set. To implement the optimization, modify a DLL’s DLL_PROCESS_ATTACH code to call DisableThreadLibraryCalls.

Do not call this function from a DLL that is linked to the static C run-time library (CRT). The static CRT requires DLL_THREAD_ATTACH and DLL_THREAD_DETATCH notifications to function properly.

Requirements

Minimum supported clientWindows XP [desktop apps
Minimum supported serverWindows Server 2003 [desktop apps
Target PlatformWindows
Headerlibloaderapi.h (include Windows.h)
LibraryKernel32.lib
DLLKernel32.dll

https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-disablethreadlibrarycalls

C#和其他大多数托管语言生成的DLL没有DllMain函数。所以,托管DLL不会收到DLL_THREAD_ATTACHDLL_THREAD_DETACH通知,这提升了性能。此外,非托管DLL可调用Win 32 DisableThreadLibraryCalls函数来决定不理会这些通知。

以上是关于C# 线程——《CLR via C#(第四版)》的主要内容,如果未能解决你的问题,请参考以下文章

《CLR via C#》之线程处理——线程池与任务

《CLR via C#》之线程处理——任务调度器

CLR via C# 学习计划

《CLR via C#》之线程处理——协作式取消和超时

CLR via C# 阅读 笔记

clr via c# clr寄宿和AppDomain