Freigeben über


Konkurrenz

Im Concurrency-Beispiel wird die Verwendung der ServiceBehaviorAttribute- mit der ConcurrencyMode-Enumeration veranschaulicht, die steuert, ob eine Instanz eines Dienstes Nachrichten sequenziell oder gleichzeitig verarbeitet. Das Beispiel basiert auf dem "Erste Schritte", der den ICalculator Servicevertrag implementiert. In diesem Beispiel wird ein neuer Vertrag, ICalculatorConcurrency, definiert, der von ICalculator erbt und zwei zusätzliche Vorgänge zum Überprüfen des Zustands der Dienstkonkurrenz bereitstellt. Durch Ändern der Parallelitätseinstellung können Sie die Verhaltensänderung beobachten, indem Sie den Client ausführen.

In diesem Beispiel ist der Client eine Konsolenanwendung (.exe) und der Dienst wird von Internetinformationsdienste (IIS) gehostet.

Hinweis

Die Einrichtungsverfahren und Build-Anweisungen für dieses Beispiel befinden sich am Ende dieses Themas.

Es stehen drei Parallelitätsmodi zur Verfügung:

  • Single: Jede Dienstinstanz verarbeitet jeweils eine Nachricht. Dies ist der Standardmäßige Parallelitätsmodus.

  • Multiple: Jede Dienstinstanz verarbeitet mehrere Nachrichten gleichzeitig. Die Dienstimplementierung muss threadsicher sein, um diesen Parallelitätsmodus zu verwenden.

  • Reentrant: Jede Dienstinstanz verarbeitet jeweils eine Nachricht, akzeptiert aber wiederholte Aufrufe. Der Dienst akzeptiert diese Anrufe nur, wenn er ausruft. Reentrant wird im ConcurrencyMode.Reentrant-Beispiel veranschaulicht.

Die Parallelität steht mit dem Instanziierungsmodus in Beziehung. Beim PerCall Instancing ist die Gleichzeitigkeit nicht relevant, da jede Nachricht von einer neuen Dienstinstanz verarbeitet wird. In der Single-Instanziierung ist entweder die Single- oder die Multiple-Parallelität relevant, je nachdem, ob die einzelne Instanz Nachrichten sequenziell oder parallel verarbeitet. In der PerSession-Instanziierung sind möglicherweise alle Parallelitätsmodi relevant.

Die Dienstklasse gibt das Parallelitätsverhalten mit dem [ServiceBehavior(ConcurrencyMode=<setting>)] Attribut an, wie im folgenden Codebeispiel gezeigt. Indem Sie ändern, welche Zeilen auskommentiert werden, können Sie in den Single und Multiple Parallelitätsmodi experimentieren. Denken Sie daran, den Dienst nach dem Ändern des Parallelitätsmodus neu zu erstellen.

// Single allows a single message to be processed sequentially by each service instance.
//[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]

// Multiple allows concurrent processing of multiple messages by a service instance.
// The service implementation should be thread-safe. This can be used to increase throughput.
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]

// Uses Thread.Sleep to vary the execution time of each operation.
public class CalculatorService : ICalculatorConcurrency
{
    int operationCount;

    public double Add(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(180);
        return n1 + n2;
    }

    public double Subtract(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(100);
        return n1 - n2;
    }

    public double Multiply(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(150);
        return n1 * n2;
    }

    public double Divide(double n1, double n2)
    {
        operationCount++;
        System.Threading.Thread.Sleep(120);
        return n1 / n2;
    }

    public string GetConcurrencyMode()
    {
        // Return the ConcurrencyMode of the service.
        ServiceHost host = (ServiceHost)OperationContext.Current.Host;
        ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
        return behavior.ConcurrencyMode.ToString();
    }

    public int GetOperationCount()
    {
        // Return the number of operations.
        return operationCount;
    }
}

Im Beispiel wird standardmäßig die Multiple-Parallelität mit der Single-Instanziierung verwendet. Der Clientcode wurde geändert, um einen asynchronen Proxy zu verwenden. Dadurch kann der Client mehrere Anrufe an den Dienst tätigen, ohne auf eine Antwort zwischen jedem Anruf zu warten. Sie können das unterschiedliche Verhalten des Dienstparallelitätsmodus beobachten.

Wenn Sie das Beispiel ausführen, werden die Vorgangsanforderungen und -antworten im Clientkonsolenfenster angezeigt. Der Parallelitätsmodus, unter dem der Dienst ausgeführt wird, wird angezeigt, jeder Vorgang wird aufgerufen, und dann wird die Vorgangsanzahl angezeigt. Beachten Sie, dass die Ergebnisse, wenn der Parallelitätsmodus ist Multiple, in einer anderen Reihenfolge als der Aufruf zurückgegeben werden, da der Dienst mehrere Nachrichten gleichzeitig verarbeitet. Durch das Ändern des Parallelitätsmodus auf Single werden die Ergebnisse in der Reihenfolge zurückgegeben, in der sie aufgerufen wurden, da der Dienst jede Nachricht sequenziell verarbeitet. Drücken Sie im Clientfenster die EINGABETASTE, um den Client zu schließen.

So können Sie das Beispiel einrichten, erstellen und ausführen

  1. Stellen Sie sicher, dass Sie das One-Time Setup-Verfahren für die Windows Communication Foundation-Beispieleausgeführt haben.

  2. Wenn Sie Svcutil.exe verwenden, um den Proxyclient zu generieren, stellen Sie sicher, dass Sie die /async Option einschließen.

  3. Um die C#- oder Visual Basic .NET-Edition der Lösung zu erstellen, befolgen Sie die Anweisungen in Building the Windows Communication Foundation Samples.

  4. Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.