Freigeben über


Auswahl einer Laufzeitbibliothek

Angenommen, Sie benötigen eine Anwendung, z. B. eine Internetserveranwendung wie FoxIsapi, in der Sie ein Formular instanziieren möchten, das für die Zuordnung zu äquivalentem HTML-Code verwendet wird. Wenn Sie die neue Laufzeitbibliothek vfp7t.dll verwenden und somit eine Reihe nicht zentraler Funktionen beseitigen, führt dies zu einer Erhöhung der Gesamtleistung Ihrer Multithread-Serveranwendungen.

Bei der Serverauswahl wird häufig fälschlicherweise davon ausgegangen, dass automatisch ein gutes Leistungsverhalten für eine Anwendung erreicht werden kann, indem bei der Erstellung der DLL angegeben wird, dass sie die neue Laufzeitbibliothek verwenden soll. In vielen Fällen trifft dies zwar tatsächlich zu, Sie sollten jedoch auch Auswirkungen der Verwendung von Visual FoxPro-API-Aufrufen sowie die Aspekte Skalierbarkeit, Reentranz und Ressourcenkonflikte berücksichtigen.

Verwenden von Visual FoxPro-API-Aufrufen

Wenn Sie Visual FoxPro-FLL- oder Standard-Windows-DLL-Bibliotheken verwenden, die die Visual FoxPro-API aufrufen, müssen Sie beim Serverentwurf einige Aspekte berücksichtigen. Die Visual FoxPro-API ermittelt nicht, zu welchem Projekt (DLL) ein bestimmter Aufruf gehört. Es besteht somit die wenn auch geringe Gefahr, dass ein API-Aufruf für das falsche Projekt erfolgt (DLL – lokaler Threadspeicher). Dies kann der Fall sein, wenn die FLL- oder DLL-Bibliothek eine Instanz aus einem anderen Visual FoxPro-DLL-Server erstellt, bevor der API-Aufruf erfolgt. Für dieses Problem gibt es eine Reihe möglicher Lösungen:

  • Erstellen Sie eine separate Kopie der Laufzeitbibliothek vfp7t.dll, und speichern Sie diese Kopie in demselben Ordner wie den DLL-Server. Der Server durchsucht zuerst immer den Serverordner, bevor er den Windows-Ordner System oder den Ordner des Clientprozesses nach bestimmten Dateien durchsucht. Steht einem Server eine eigene Laufzeitbibliothek zur Verfügung, treten keine Konflikte mit anderen DLLs auf (vorausgesetzt, diese anderen DLLs befinden sich nicht in demselben Ordner). Da dieser Vorgang (automatisches Kopieren/Umbenennen der Laufzeitbibliothek) für die Laufzeitbibliothek Vfp7r.dll standardmäßig erfolgt, treten die zuvor beschriebenen Probleme bei API-Aufrufen nur auf, wenn die Laufzeitbibliothek Vfp7t.dll verwendet wird.
  • Begrenzen Sie die Anwendung auf einen einzelnen DLL-Server. Wenn Sie mehrere DLL-Server (Projekte) verwenden, besteht die Gefahr, dass API-Konflikte auftreten. Bedenken Sie, dass ein Projekt mehrere OLEPUBLIC-Klassen enthalten kann. Es ist also nicht notwendig, für jede OLEPUBLIC-Klasse ein eigenes Projekt zu erstellen. Bedenken Sie, dass es bei freigegebenen Computerservern möglich ist, dass andere Personen weitere Visual FoxPro-COM-Server installieren, die bei gleichzeitiger Ausführung möglicherweise Konflikte mit den von Ihnen installierten Servern auslösen.

Skalierbarkeitsaspekte

Die Multithread-Laufzeitumgebung von Visual FoxPro ermöglicht die Erstellung extrem skalierbarer, prozessinterner Visual FoxPro-Server. Obwohl die Skalierbarkeit der Server automatisch von der Laufzeitbibliothek gesteuert wird, ist es möglich, dass bestimmte enge Codeschleifen den häufigen Threadwechsel nicht zulassen. Dies kann z. B. bei einer sehr engen DO WHILE-Schleife der Fall sein. Falls Probleme mit der Skalierbarkeit auftreten, können Sie Code, wie im folgenden Beispiel aufgezeigt, einbinden, durch den der Prozessor zum Threadwechsel gezwungen wird:

DECLARE Sleep IN Win32API INTEGER   
SLEEP(0)

Auch wenn Sie das Multithreading auf einem Computer mit nur einem Prozessor verwenden können, sollten Sie bedenken, dass dies nicht unbedingt zu dem erwarteten Ergebnis führt. So können auf einem Computer mit nur einem Prozessor nur dann Leistungsverbesserungen durch den Einsatz des Multithreadings erzielt werden, wenn eine Mischung aus langen und kurzen Tasks vorliegt. Für die in diesem Beispiel beschriebenen Methodenaufrufe kann das Multithreading zu einer Verlangsamung der Ausführung führen.

In dem Beispiel werden die Methoden A und B gleichzeitig aufgerufen. In einer Singlethread-Komponente werden die Anforderungen serialisiert, so dass die Ausführung von B erst dann beginnt, wenn die Ausführung von A abgeschlossen ist. Beim Multithreading konkurrieren die beiden aktiven Threads um die Aufmerksamkeit des Prozessors.

Hierdurch nimmt nicht nur die durchschnittliche wahrgenommene Ausführungszeit zu, sondern es wird auch mehr Prozessorzeit für den Wechsel zwischen den Threads aufgewendet.

Das Problem besteht darin, dass die Ausführung von Methode A ungefähr genauso lange dauert wie die Ausführung von Methode B.

Wenn für die Ausführung von Methode B beispielsweise nur drei Zeitscheiben erforderlich wären, würde der Benutzer des Systems eine deutliche Verbesserung bei der Antwortgeschwindigkeit von Methode B und nur eine geringfügige Verlängerung der Ausführungszeit für Methode A wahrnehmen.

Zu den Szenarien, in denen das Multithreading die deutlichsten Verbesserungen erzielt, zählen Situationen, in denen die meisten Threads für eine nicht unerhebliche Dauer blockiert sind (weil sie z. B. auf eine Datei-E/A warten), so dass andere Threads zu jedem beliebigen Zeitpunkt Code ausführen können.

Wenn Sie eine Anwendung entwerfen, die auf einem Computer mit nur einem Prozessor ausgeführt wird, und diese Anwendung sich dadurch auszeichnet, dass nur geringfügige Threadblockierungen auftreten, sollten Sie die Verwendung der Laufzeitbibliothek vfp7r.dll erwägen. Auf Multiprozessorcomputern und für die meisten anderen Anwendungen sollten Sie für DLL-Server die Verwendung von vfp7t.dll in Betracht ziehen.

Reentranz

Im Rahmen des Apartmentmodells bezeichnet Reentranz die folgende Abfolge von Ereignissen:

  1. Der Ausführungsthread eines Apartments tritt in den Code eines Objekts ein, da eine Eigenschaft oder Methode aufgerufen wurde.
  2. Während sich der Thread in der Eigenschaft oder Methode befindet, ruft ein anderer Thread eine Eigenschaft oder Methode des Objekts auf, und die Anforderung wird durch die Automatisierung serialisiert, d. h., die Anforderung wird in eine Warteschlange eingereiht, bis der Thread, der das Apartment des Objekts besitzt, das Element beendet, das er derzeit ausführt.
  3. Bevor der Thread das Ende des Elements erreicht hat, führt er Code aus, durch den die Steuerung des Prozessors abgegeben wird.
  4. Die Automatisierung teilt dem Thread mit, dass er die Ausführung der serialisierten Anforderung aufnehmen soll, so dass der Thread erneut in den Code des Objekts eintritt.

Die neue Anforderung kann sich auf das Element beziehen, das der Thread bereits ausgeführt hat – in diesem Fall tritt der Thread ein zweites Mal in das Element ein – oder sie kann sich auf ein anderes Element beziehen. Wenn das zweite Element die Steuerung nicht abgibt, wird dessen Ausführung vor dem ersten Element beendet. Werden hierdurch Daten auf Modulebene geändert, die von dem ersten Element verwendet wurden, kann dies zu einem nicht gewünschten Ergebnis führen.

Durch die Serialisierung von Eigenschaften- und Methodenaufrufen für jedes Apartment bietet die Automatisierung Schutz vor Reentranz, es sei denn, die Steuerung des Prozessors wird durch den Code selbst abgegeben. Die Übergabe der Steuerung des Prozessors durch Code kann folgendermaßen stattfinden:

  • Aufrufen von DoEvents.
  • Aufrufen der Eigenschaften oder Methoden eines Objekts in einem anderen Thread oder in einem anderen Prozess. Durch das Festlegen der AutoYield-Eigenschaft des Anwendungsobjekts auf Falsch (.F.) wird die Verarbeitung von ausstehenden Ereignissen zwischen der Ausführung von Codezeilen ausgesetzt.
  • Aufrufen einer thread- oder prozessübergreifenden Methode aus einer Methode heraus.

Sie sollten Code, der die Steuerung des Prozessors abgibt nur dann verwenden, wenn der gesamte Code eines Objekts so sorgfältig programmiert wurde, dass es keine Rolle spielt, wenn zwei Elemente gleichzeitig ausgeführt werden.

Ressourcenkonflikte

Durch die neue Laufzeitbibliothek vfp7t.dll wird verhindert, dass Objekte auf die Anwendungsdaten der jeweils anderen Objekte zugreifen. Dies gilt sowohl für deklarierte als auch für integrierte globale Umgebungsdaten. Einige Ressourcen können Konflikte auslösen; dies umfasst die Folgenden:

  • Dateien
  • Registry
  • Daten

Ressourcenkonflikte im Bereich der Datei-E/A können problemlos durch Code aufgelöst werden, da die Dateiverwaltung vom Betriebssystem übernommen wird. Wenn ein Server eine Datei verwendet, kann er die Datei öffnen (und sperren), so dass für andere Objekte erkennbar ist, dass die Datei verwendet wird. Ein Server, der sorgfältig programmiert wurde, wird nun warten, bis die Datei wieder verfügbar ist oder ein anderes Verfahren einsetzen, um den Fehler elegant aufzulösen. Dateien können auch für den gemeinsamen Zugriff geöffnet werden; in diesem Fall sollte der Server berücksichtigen, dass Werte von anderen Objekten geändert werden können.

Ein gängiges Beispiel für dieses Szenario sind INI-Dateien, deren Werte von unterschiedlichen Objekten gelesen und geschrieben werden können. Das Lesen und anschließende Schreiben eines Wertes in einer INI-Datei setzt sich aus zwei Schritten zusammen. Es ist daher möglich, dass der Wert, der von einem Client gelesen wurde, nicht mehr mit dem Wert übereinstimmt, den er später überschreibt, da der Wert in der Zwischenzeit eventuell von einem anderen Client geändert wurde. Für derartige Fälle sollte eine Strategie zur Konfliktauflösung implementiert werden.

Wie in INI-Dateien werden auch in der Registrierung Einstellungen gespeichert, auf die mehrere Clients zugreifen können. Die Anwendung sollte für den Zugriff auf die Registrierung gängige Routinen der Windows-API (z. B. FoxPro Foundation Classes in REGISTRY.VCX) verwenden. Auch hier sollte der Serverentwurf die Möglichkeit berücksichtigen, dass Registrierungsschlüsselwerte zwischen dem Lesen und dem Schreiben des Schlüssels geändert werden. Die Routinen der Windows-API sind so konzipiert, dass die Notwendigkeit der Konfliktauflösung erst gar nicht entsteht.

Die Bearbeitung von Daten kann zu zahlreichen Konflikten führen. Glücklicherweise stellt die umfangreiche Visual FoxPro-Sprache, die in den Laufzeitbibliotheken bereitgestellt wird, sämtliche Informationen und Funktionen bereit, die erforderlich sind, um Ressourcenkonflikte aufzulösen. Weitere Informationen zur Handhabung gemeinsam verwendeter Daten finden Sie unter Programmieren für freigegebenen Zugriff.

Siehe auch

Steuerung der Aufrufblockierung | In Laufzeiten unterstützte Sprachen | Interoperabilität und das Internet | Programmieranmerkungen zu Automatisierungsservern | FoxIsapi