线程池的线程创建事件

4
有没有办法在新的线程池线程创建时被通知(例如通过事件或回调)?我正在开发一个使用 P/Invoke 调用 pjlib 库的 .Net 控制台应用程序。该库要求使用其任何 API 的每个线程必须先通过 pj_thread_register API 进行注册:

向 PJLIB 注册通过外部或本地 API 创建的线程。必须在注册线程的上下文中调用此函数。当由外部函数或 API 调用创建线程时,必须使用 pj_thread_register() 将其“注册”到 PJLIB 中,以便它可以与 PJLIB 的框架协作。在注册期间需要维护一些数据,并且这些数据必须在线程的生命周期内保持可用。

当尝试从未注册的线程调用任何 pjlib 函数时,库实际上会断言并显示以下消息:

Calling pjlib from unknown/external thread. You must
register external threads with pj_thread_register()
before calling any pjlib functions.

现在,应用程序的业务逻辑使用了 asyncawait,因为它是控制台应用程序,所以 SynchronizationContext 为空,这意味着所有的继续都将在线程池线程上运行,包括对 pjsip API 的 P/Invoke 调用,需要在调用任何 pjsip API 之前调用 pj_thread_register(),以确保新创建的线程池线程不会在注册自己之前尝试使用任何 pjsip API。
我想,如果可以在每个新线程池线程被创建时得到通知(通过在新线程的上下文中调用回调函数),那么就可以使用该回调函数仅注册新线程一次。是否有一种方法接收此类通知?
或者,我可以在主线程或某些专用线程上使用 SynchronizationContext(例如 Stephen Cleary 的 AsyncContext 或 Stephen Toub 的 AsyncPump),并在创建它们时立即注册它们,但这意味着需要重新设计应用程序,可能朝着演员模型的方向发展,是否有其他方法来面对这种情况?

你好 @Oaraisi。你找到关于你的问题的解决方案了吗?如果是的话,你能分享一下代码片段吗? - undefined
1
嗨,我遵循了Stephen Cleary在接受的解决方案中的建议:为了确保每个线程只调用一次pj_thread_register,我使用了[ThreadStatic]静态布尔标志。 [ThreadStatic]属性(https://learn.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=net-7.0)确保每个线程都为该字段获取其唯一值。 因此,如果一个async/await方法的继续在同一个线程池的线程上运行多次,它只会调用一次pj_thread_register API。[ThreadStatic] static bool _pjInitialized = false; if (!_pjInitialized) PjThreadRegister(); - undefined
嗨,我正在使用C#包装器,libRegisterThread函数需要线程名称作为参数。你是如何决定线程名称的呢? - undefined
1
在我们自己的C#包装器(一个围绕pjproject API的薄P/Invoke层)中,我们只需使用Thread.CurrentThread.Name:var status = pj_thread_register(Thread.CurrentThread.Name, desc, ref t);。Thread.CurrentThread.Name可能为空,但是在查看pj_thread_register的实现(无论是在Windows还是Unix上),在使用pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), cstr_thread_name, thread->idthread);之前,会对const char *cstr_thread_name进行空检查,因此这不是一个问题。无论如何,选择一个有意义的名称都是明智的(例如用于日志记录)。 - undefined
1个回答

4
可能可以使用性能分析API或ETW来检测所有线程池创建事件。虽然我不确定在这些事件的上下文中执行代码有多容易,但是可以尝试。
我建议在您的Interop层中使用[ThreadStatic] static bool PjInitialized;字段,并在该层的每个调用中添加一个检查。如果未初始化,则在实际调用之前调用pj_thread_register。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接