Search code examples
c#async-awaitthreadpoolpjsipnito.asyncex

ThreadPool's Thread creation event


Is there a way to be notified (e.g. via an event or a callback) whenever a new ThreadPool thread is created?
I'm working on a .net console app that is using pjlib library via P/Invoke. This library requires that every thread that uses any of its APIs has to be previously registered via pj_thread_register API:

Register a thread that was created by external or native API to PJLIB. This function must be called in the context of the thread being registered. When the thread is created by external function or API call, it must be 'registered' to PJLIB using pj_thread_register(), so that it can cooperate with PJLIB's framework. During registration, some data needs to be maintained, and this data must remain available during the thread's lifetime.

When trying to call any pjlib function form an unregistered thread the library will indeed assert with the message:

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

Now, the application's business logic uses async and await, and being it a console app the SynchronizationContext is null, meaning all continuations will run on ThreadPool's threads, including the P/Invokes calls to pjsip APIs, making necessary to call pj_thread_register() before every call to any of the pjsip APIs, to be sure that a newly created ThreadPool's thread won't try to use any pjsip API before registering itself.

I thought that if I could be notified (with a callback that gets called in the context of the newly created thread) whenever a new threadpool thread is created I could use this callback to register the new thread only once. Is there a way to receive such a notification?

Alternatively I could use a SynchronizationContext (e.g. Stephen Cleary's AsyncContext or Stephen Toub's AsyncPump) on the main or on some dedicated threads (and register them as soon as I create them), but this would mean to redesign the application, maybe going towards an actor model, is there an alternative approach to face this kind of situations?


Solution

  • It might be possible to use profiling APIs or ETW to detect all thread pool creation events. I'm not sure how easy it would be to execute code in the context of that thread as a result of those events, though.

    I would recommend using a [ThreadStatic] static bool PjInitialized; field in your interop layer, and add a check to every call at that layer. If it's not initialized, then call pj_thread_register before the actual call.