Out-Of-Process COM, CCW, QueueUserAPC



  • Ahoi,

    ich hab nach einigem googeln und rumprobieren einen Out-Of-Process COM in C# gebastelt. Funktioniert soweit auch alles ganz gut, bis auf das gute alte Problem: deterministische Finalisierung.
    Dummerweise weigert sich MS ja hartnäckig eine Möglichkeit für die Weiterleitung des "final release" des CCW zu schaffen.

    Ich brauch aber mehr oder weniger deterministische Finalisierung (sprich "bald" reicht, "irgendwann" reicht nicht). Also hab' ich mir dazu ein hübsches Singleton gebaut wo alle COM Objekte registriert werden, und einen Thread der dann hin und wieder mal den CCW Ref-Count dieser Objekte kontrolliert -- und bei Ref-Count 0 Dispose aufruft.

    Bei Objekten die vom Client per CoCreateInstance erzeugt werden funktioniert das auch ganz toll - da ist der CCW Ref-Count im Konstruktor bereits > 0.

    Dumm ist es nur bei Objekten die ich im Out-Of-Process Server selbst instanziere (ganz normal mit new ), und dann als COM-Interface zurückgebe. Zu dem Zeitpunkt wo der Konstruktor läuft gibt es da natürlich noch keine COM Referenzen, das Ding ist ja erstmal ein ganz normales Objekt.

    Wenn jetzt genau zur ungünstigsten Zeit mein "COM Object Disposer" Thread los laufen würde, würde dieser nen CCW Ref-Count von 0 feststellen, und das Objekt disposen.

    Als Workaround hab' ich jetzt mal QueueUserAPC verwendet. Statt die selbst erzeugten Objekte direkt in die Liste einzutragen, beantrage ich einen Callback mittels QueueUserAPC (über PInvoke).
    Und im Callback wird das Objekt dann eingetragen.

    Das scheint auch zu funktionieren - anscheinend wartet der Thread der die COM RPC Aufrufe abarbeitet irgendwo in einem "alertable" Zustand, und das erst ausreichend spät, nachdem das zurückgegebene Interface bereits "gemarshalt" wurde.

    (Natürlich ist diese Lösung auch alles andere als optimal, da man immer aufpassen muss dass nach QueueUserAPC kein eigener Code mehr kommt der alertable wartet, aber OK, damit könnte ich leben.)

    Nur frage ich mich jetzt... ist das halbwegs sicher?
    Bzw. fällt jemandem von euch eine bessere Möglichkeit ein freigegebene COM Objekte "einzuklauben"?
    Eine Möglichkeit abzufragen ob der CCW für ein Objekt überhaupt schon erzeugt wurde würde auch reichen -- nur hab ich keine gefunden ( Marshal.GetIUnknownForObject ist einfach kommentarlos erfolgreich, selbst wenn das Objekt noch keinen CCW hat).


Anmelden zum Antworten