Maison >développement back-end >C++ >Comment résoudre les blocages dans les threads STA à l'aide de StaTaskScheduler et BlockingCollection ?

Comment résoudre les blocages dans les threads STA à l'aide de StaTaskScheduler et BlockingCollection ?

Linda Hamilton
Linda Hamiltonoriginal
2025-01-11 10:33:44202parcourir

How to Resolve Deadlocks in STA Threads Using StaTaskScheduler and BlockingCollection?

Pompage des messages StaTaskScheduler et STA

Question :

Un blocage se produit lors de l'utilisation de StaTaskScheduler et BlockingCollection sur le thread STA en raison du manque de pompage des messages.

Solution :

Utilisez MsgWaitForMultipleObjectsEx au lieu de CoWaitForMultipleHandles pour implémenter un contexte de synchronisation personnalisé avec des capacités de pompage de messages.

Instructions étape par étape :

  1. Comprenez le problème : Le STA TaskScheduler ne pompe pas automatiquement les messages sur le fil de discussion STA.
  2. Cause première identifiée : L'opération de blocage effectuée par BlockingCollection ne pompe pas les messages.
  3. Créez un contexte de synchronisation personnalisé : Remplacez SynchronizationContext.Wait pour utiliser MsgWaitForMultipleObjectsEx pour implémenter le pompage de messages et afficher/envoyer des messages.
  4. Installer un contexte de synchronisation personnalisé : Installer un contexte de synchronisation personnalisé sur chaque thread STA créé par le StaTaskScheduler.
  5. Utilisez un contexte de synchronisation personnalisé : Utilisez StaTaskScheduler avec un contexte de synchronisation personnalisé pour planifier des tâches afin d'assurer le pompage des messages.

Instructions de mise en œuvre :

  • Détectez les messages entrants en utilisant MWMO_INPUTAVAILABLE avec le drapeau MsgWaitForMultipleObjectsEx.
  • Pompez manuellement les messages en appelant Wait et PeekMessage(PM_REMOVE) dans la méthode DispatchMessage du contexte de synchronisation personnalisé.
  • Gérez les temps morts et les conditions de course potentielles avec élégance.

Avantages :

  • Résout les problèmes de blocage en garantissant que les messages sont traités sur le thread STA.
  • Maintenir l'environnement d'exécution STA correct pour les objets COM hérités.
  • Préservez l'affinité des threads lors de l'utilisation des continuations d'attente ultérieures.

Exemple de code :

<code class="language-csharp">// 带有消息泵送的自定义同步上下文
class CustomSynchronizationContext : SynchronizationContext
{
    protected override void OnWait(bool unused)
    {
        const uint QS_MASK = 0x0001;
        const uint MWMO_INPUTAVAILABLE = 0x0004;

        var nativeResult = MsgWaitForMultipleObjectsEx(
            0, null, WAIT_INFINITE, QS_MASK, MWMO_INPUTAVAILABLE);

        var msg = new MSG();
        while (true)
        {
            if (nativeResult == WAIT_OBJECT_0)
                break;

            if (PeekMessage(out msg, IntPtr.Zero, 0, 0, PM_REMOVE))
            {
                TranslateMessage(ref msg);
                DispatchMessage(ref msg);
            }

            nativeResult = MsgWaitForMultipleObjectsEx(0, null, 0, QS_MASK, MWMO_INPUTAVAILABLE);
        }
    }
}

// 使用方法
using (var staThread = new ThreadWithAffinityContext(true, true))
{
    staThread.Run(async () =>
    {
        // 在 STA 线程上安装自定义同步上下文
        SynchronizationContext.SetSynchronizationContext(new CustomSynchronizationContext());

        // 使用消息泵送的 STA 线程代码...
    });
}</code>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn