Frage

Ich habe eine COM-Komponente in .NET geschrieben und wenn ich versuche, eine Sperre auf einem beliebiges Objekt in jedem Verfahren zu übernehmen (das von nicht verwalteten Code aufgerufen wird, im Gespräch mit meiner COM-Komponente) erhalte ich eine Ausnahme.

Ich habe nicht den genauen Wortlaut der Ausnahme in diesem Moment, aber es war auch nicht viel hilfreich.

Also meine Frage, unter welchen Umständen eine Sperre (SyncObject) würde eine Ausnahme auslösen? Hier sind einige Fakten:

  • SyncObject ist nicht null
  • SyncObject nicht bereits gesperrt

Wäre es etwas mit Rufenen läuft in STA (Single Threaded Apartment) oder MTA (Multi-Threaded Apartment) zu tun?

War es hilfreich?

Lösung

dieser Seite :

  

Jede Sperre Erwerb könnte eine Ausnahme werfen. Seien Sie darauf vorbereitet.

     

Die meisten Schlösser lazily ein Ereignis zuzuweisen, wenn ein Lock-Acquisition Behauptung trifft, einschließlich CLR-Monitore. Diese Zuordnung kann in der Nebenressourcenbedingungen versagen, wodurch Ooms vom Eingang in die Verriegelungs Ursprung. (Beachten Sie, dass ein typischer nicht-blockierende Spin-Lock nicht mit OOM fehlschlagen kann, was es ermöglicht, in einigen begrenzten Ressourcen Szenarien verwendet werden, wie beispielsweise in einem CER). In ähnlicher Weise ein Host wie SQL Server Deadlock-Erkennung durchführen kann und auch solche Deadlocks bricht durch Erzeugen von Ausnahmen, die von der Enter-Anweisung stammen, als System.Runtime.InteropServices.COMException manifestiert.

     

Oft gibt es nicht viel, das in Reaktion auf eine solche Ausnahme gemacht werden kann. Aber der zuverlässigkeits und sicherheitssensiblen Code, der robust mit Versagen umgehen müssen soll diesen Fall in Betracht ziehen. Wir hätten gerne es der Fall sein, die Host-Deadlocks reagiert werden kann intelligent, aber die meisten Bibliothekscode kann auf einen sicheren Punkt auf dem Stapel nicht intelligent entspannen, so dass es-off zurück und wiederholen Sie den Vorgang. Es gibt einfach zu viel Quer Bibliothek Mischung auf einem typischen Stapel. Aus diesem Grunde Timeout-basierten Monitor-Akquisitionen mit TryEnter sind in der Regel eine schlechte Idee für Deadlock Prävention.

So wie man lesen kann, scheint es, dass unter ressourcenbeschränkten Bedingungen wir Ausnahmen von der Enter-Methode des Monitors geworfen bekommen könnten, die sperren (o) intern verwendet.

Also vielleicht Ihre Lösung ist so etwas wie ein Spin-warten?

{
    uint iters = 0;
    while (!cond) {
        if ((++iters % 50) == 0) {
            // Every so often we sleep with a 1ms timeout (see #30 for justification).
            Thread.Sleep(1);
        } else if (Environment.ProcessorCount == 1) {
            // On a single-CPU machine we yield the thread.
            Thread.Sleep(0);
        } else {
            // Issue YIELD instructions to let the other hardware thread move.
            Thread.SpinWait(25);
        }
    }
}

Wo cond könnten einige sein

private volatile int cond = 0

mit beispielsweise verwendet Interlocked.CompareExchange, wo Sie zum Beispiel ändern Thread.Current.ManagedThreadID oder etwas anderes nicht-Null?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top