Wir haben einen WCF-Webservice-Vorgang, der zum Generieren von PDF-Dateien verwendet wird. Dazu verwenden wir ein Drittanbieter-Tool (speziell Syncfusion), das wir im Moment möglicherweise nicht ersetzen können.
Das Problem ist, dass das Tool eines Drittanbieters ein Problem mit Multi-Threading hat und in einigen Fällen nicht funktioniert, wenn mehrere Aufrufe gleichzeitig an den Web-Service gesendet werden.
Wir können das Problem beheben, indem wir lock
verwenden und sicherstellen, dass nur ein Thread den kritischen Abschnitt ausführt:
Meine Frage ist: Ist das eine gute Idee? Wird es irgendwelche Probleme geben, wenn wir einen solchen Code in einem Web-Service haben?
Hinweis
Dies ist keine Frage über Syncfusion. Dies ist eine Frage zur Verwendung von lock
in einem Webdienst. Ändern Sie die Tags bitte nicht in Syncfusion.
WCF unterstützt synchronisiertes Aufrufen Ihrer Dienstobjekte. Je nach Ihren Anforderungen können Sie sich die folgenden zwei Eigenschaften ansehen:
Wenn Sie mehrere Instanzen einer Drittanbieterkomponente nicht starten können und die Komponente keinen gleichzeitigen Zugriff zulässt (im schlimmsten Fall), können Sie InstanceContextMode = Single und ConcurrencyMode = Single angeben. In diesem Fall wird WCF nur eine einzelne Kopie Ihres WCF-Objekts instanziieren (von dem ich annahm, dass es sich um einen Wrapper um die Komponente von Drittanbietern handelt), und nur eine Anforderung wird gleichzeitig verarbeitet. Die Anfragen werden in eine FIFO-Art eingereiht und verarbeitet. Sie müssen die Sperre in Ihrem wcf-Dienst nicht verwenden, da die WCF-Laufzeit dafür sorgt, dass Sie den Zugriff auf Ihre wcf-Objekte synchronisiert haben.
Das Problem, das ich hier sehe, ist Ressourcenknappheit.
Es gibt keine FIFO-Regel, die Sperren umgibt. Also, wenn es eine kontinuierliche Last gibt, könnten Sie dieses Szenario bekommen:
A
beansprucht die Sperre B
wartet auf die Sperre C
wartet auf die Sperre A
gibt die Sperre frei. Die Sperre wird dem Thread C
beliebig zugewiesen.
D
wartet auf die Sperre. Jetzt haben Sie den Thread B
und D
beide warten. C
gibt die Sperre frei. Auch wenn der Thread B
am längsten gewartet hat, wird dem Thread D
die Sperre willkürlich erteilt. Und so geht es weiter, bis der WCF-Aufruf abläuft und Sie einen Fehler erhalten, der unmöglich zu reproduzieren ist.
Wenn ich dies implementieren müsste, hätte ich einen einzigen Worker-Thread, der für das Generieren der PDF-Dateien zuständig ist. Dieser Thread wird gestartet, wenn der Dienst zum ersten Mal gestartet wird, und wartet darauf, einen Job aus einer Jobwarteschlange abzuholen. Jede WCF-Abfrage wird eine Anforderung in diese Warteschlange stellen, und es gibt eine Möglichkeit, sie zu blockieren, bis sie weiß, dass der Job verarbeitet wurde.
.NET 4.0 bietet die BlockingCollection
-Klasse, um damit zu helfen. (Siehe diese Frage )
Dies gibt Ihnen den Ansatz ohne eine vollständige Lösung, weil es kein triviales Problem ist. Viel Glück!
Tags und Links wcf c# multithreading web-services locking