Udostępnij przez


Uzyskiwanie dostępu do usług przy użyciu klienta

Aplikacje klienckie muszą tworzyć, konfigurować i używać obiektów klienta lub kanału WCF do komunikowania się z usługami. Temat Omówienie klienta programu WCF zawiera omówienie obiektów i kroków związanych z tworzeniem podstawowych obiektów klienta i kanału oraz ich używaniem.

Ten temat zawiera szczegółowe informacje na temat niektórych problemów z aplikacjami klienckimi oraz obiektami klienta i kanału, które mogą być przydatne w zależności od scenariusza.

Przegląd

W tym temacie opisano zachowanie i problemy związane z:

  • Okresy istnienia kanału i sesji.

  • Obsługa wyjątków.

  • Zrozumienie problemów z blokowaniem.

  • Interakcyjne inicjowanie kanałów.

Okresy istnienia kanału i sesji

Aplikacje programu Windows Communication Foundation (WCF) obejmują dwie kategorie kanałów, datagram i sesji.

Kanał datagramowy to kanał, w którym wszystkie komunikaty są nieskorelowane. W przypadku kanału datagramu, jeśli operacja wejściowa lub wyjściowa zakończy się niepowodzeniem, następna operacja zwykle nie jest dotknięta, a ten sam kanał może zostać ponownie użyty. W związku z tym kanały datagramu zwykle nie ulegają awariom.

Kanały sessionful to jednak kanały z połączeniem do innego punktu końcowego. Komunikaty w sesji po jednej stronie są zawsze skorelowane z tą samą sesją po drugiej stronie. Ponadto obaj uczestnicy sesji muszą zgodzić się, że wymagania ich rozmowy zostały spełnione, aby ta sesja została uznana za pomyślną. Jeśli nie mogą się zgodzić, kanał z sesjami może ulec awarii.

Otwórz klientów jawnie lub niejawnie, wywołując pierwszą operację.

Uwaga / Notatka

Próba jawnego wykrycia kanałów sesji z błędami nie jest zwykle przydatna, ponieważ moment powiadomienia zależy od implementacji sesji. Na przykład, ponieważ System.ServiceModel.NetTcpBinding (z wyłączoną niezawodną sesją) wyświetla sesję połączenia TCP, jeśli nasłuchujesz zdarzenia ICommunicationObject.Faulted w usłudze lub kliencie, prawdopodobnie zostaniesz szybko powiadomiony w przypadku awarii sieci. Jednak niezawodne połączenia (ustanowione przez wiązania, w których System.ServiceModel.Channels.ReliableSessionBindingElement jest włączone) są zaprojektowane do ochrony usług przed małymi awariami sieci. Jeśli sesję można ponownie ustanowić w rozsądnym okresie czasu, to samo powiązanie, skonfigurowane z myślą o niezawodnych sesjach, może nie spowodować błędu, dopóki przerwa nie będzie kontynuowana przez dłuższy czas.

Większość powiązań dostarczanych przez system (które udostępniają kanały w warstwie aplikacji) używa sesji domyślnie, ale System.ServiceModel.BasicHttpBinding nie. Aby uzyskać więcej informacji, zobacz Using Sessions (Korzystanie z sesji).

Właściwe użycie sesji

Sesje umożliwiają określenie, czy cała wymiana komunikatów została ukończona i czy obie strony uznały ją za pomyślną. Zaleca się, aby aplikacja wywołująca otworzyła kanał, użyła go, a następnie zamknęła w jednym bloku try. Jeśli kanał sesji jest otwarty, a ICommunicationObject.Close metoda zostanie wywoływana raz i zakończy się powodzeniem, sesja zakończyła się pomyślnie. Powodzenie w tym przypadku oznacza, że wszystkie dostawy spełniły gwarancje wymagane przez określone powiązanie, a druga strona nie wywołała ICommunicationObject.Abort na kanale przed wywołaniem Close.

W poniższej sekcji przedstawiono przykład tego podejścia klienta.

Obsługa wyjątków

Obsługa wyjątków w aplikacjach klienckich jest prosta. Jeśli kanał jest otwarty, używany i zamknięty wewnątrz bloku try, konwersacja zakończyła się pomyślnie, chyba że zostanie zgłoszony wyjątek. Zazwyczaj, jeśli zostanie zgłoszony wyjątek, konwersacja zostanie przerwana.

Uwaga / Notatka

Korzystanie z instrukcji using (Using w Visual Basic) nie jest zalecane. Wynika to z faktu, że koniec instrukcji using może powodować wyjątki, które mogą maskować inne wyjątki, o których możesz potrzebować wiedzieć. Aby uzyskać więcej informacji, zobacz artykuł Użyj poleceń Zamknij i Anuluj, aby zwolnić zasoby klienta programu WCF.

Poniższy przykład kodu przedstawia zalecany wzorzec klienta przy użyciu bloku try/catch, a nie instrukcji using .

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    SampleServiceClient wcfClient = new SampleServiceClient();
    try
    {
      // Making calls.
      Console.WriteLine("Enter the greeting to send: ");
      string greeting = Console.ReadLine();
      Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));

      Console.WriteLine("Press ENTER to exit:");
      Console.ReadLine();

      // Done with service.
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException<GreetingFault> greetingFault)
    {
      Console.WriteLine(greetingFault.Detail.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (FaultException unknownFault)
    {
      Console.WriteLine("An unknown exception was received. " + unknownFault.Message);
      Console.ReadLine();
      wcfClient.Abort();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
      Console.ReadLine();
      wcfClient.Abort();
    }
  }
}

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports Microsoft.WCF.Documentation

Public Class Client
    Public Shared Sub Main()
        ' Picks up configuration from the config file.
        Dim wcfClient As New SampleServiceClient()
        Try
            ' Making calls.
            Console.WriteLine("Enter the greeting to send: ")
            Dim greeting As String = Console.ReadLine()
            Console.WriteLine("The service responded: " & wcfClient.SampleMethod(greeting))

            Console.WriteLine("Press ENTER to exit:")
            Console.ReadLine()

            ' Done with service. 
            wcfClient.Close()
            Console.WriteLine("Done!")
        Catch timeProblem As TimeoutException
            Console.WriteLine("The service operation timed out. " & timeProblem.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch greetingFault As FaultException(Of GreetingFault)
            Console.WriteLine(greetingFault.Detail.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch unknownFault As FaultException
            Console.WriteLine("An unknown exception was received. " & unknownFault.Message)
            Console.ReadLine()
            wcfClient.Abort()
        Catch commProblem As CommunicationException
            Console.WriteLine("There was a communication problem. " & commProblem.Message + commProblem.StackTrace)
            Console.ReadLine()
            wcfClient.Abort()
        End Try
    End Sub
End Class

Uwaga / Notatka

Sprawdzanie wartości właściwości ICommunicationObject.State jest warunkiem rywalizacji i nie jest zalecane do określenia, czy ponownie użyć kanał lub go zamknąć.

Kanały datagramu nigdy nie są błędne, nawet jeśli wyjątki wystąpią po ich zamknięciu. Ponadto klienci niedupleksowi, którzy nie mogą uwierzytelniać się przy użyciu bezpiecznej konwersacji, zwykle zgłaszają błąd System.ServiceModel.Security.MessageSecurityException. Jeśli jednak klient dupleksu używający bezpiecznej konwersacji nie może się uwierzytelnić, klient otrzyma zamiast tego System.TimeoutException .

Aby uzyskać więcej informacji na temat pracy z informacjami o błędach na poziomie aplikacji, zobacz Określanie i obsługa błędów w kontraktach i usługach. Oczekiwane wyjątki opisują oczekiwane wyjątki i pokazują, jak je obsługiwać. Aby uzyskać więcej informacji na temat obsługi błędów podczas opracowywania kanałów, zobacz Obsługa wyjątków i błędów.

Blokowanie i wydajność klienta

Gdy aplikacja wykonuje synchroniczne wywołanie operacji typu request-reply, klient oczekuje, aż zostanie odebrana wartość zwracana lub zgłoszony zostanie wyjątek (taki jak System.TimeoutException). To zachowanie jest podobne do zachowania lokalnego. Gdy aplikacja synchronicznie wywołuje operację na obiekcie lub kanale klienta WCF, klient nie zwraca, dopóki warstwa kanału nie będzie mogła zapisać danych w sieci lub do momentu zgłoszenia wyjątku. I chociaż wzorzec wymiany komunikatów jednokierunkowych (określony przez oznaczenie operacji z ustawioną OperationContractAttribute.IsOneWay wartością true) może sprawić, że niektórzy klienci będą bardziej responsywni, operacje jednokierunkowe mogą być również blokowane, w zależności od powiązania i komunikatów, które zostały już wysłane. Operacje jednokierunkowe dotyczą tylko wymiany komunikatów, nie więcej i nie mniej. Aby uzyskać więcej informacji, zobacz One-Way Services.

Duże fragmenty danych mogą spowalniać przetwarzanie klienta niezależnie od wzorca wymiany komunikatów. Aby dowiedzieć się, jak rozwiązywać te problemy, zobacz Duże dane i przesyłanie strumieniowe.

Jeśli aplikacja musi wykonać więcej pracy podczas wykonywania operacji, należy utworzyć parę metod asynchronicznych w interfejsie kontraktu usługi, który implementuje klient WCF. Najprostszym sposobem na wykonanie tej czynności jest użycie przełącznika /async narzędzia ServiceModel Metadata Tool (Svcutil.exe). Przykład można znaleźć w przewodniku Jak wywoływać operacje usługi asynchronicznie.

Aby uzyskać więcej informacji na temat zwiększania wydajności klienta, zobacz Middle-Tier Aplikacje klienckie.

Umożliwianie użytkownikowi dynamicznego wybierania poświadczeń

Interfejs IInteractiveChannelInitializer umożliwia aplikacjom wyświetlanie interfejsu użytkownika, który pozwala użytkownikowi wybrać poświadczenia, z którymi kanał jest tworzony przed uruchomieniem zegarów limitu czasu.

Deweloperzy aplikacji mogą korzystać z wstawionego IInteractiveChannelInitializer obiektu na dwa sposoby. Aplikacja kliencka może wywołać albo ClientBase<TChannel>.DisplayInitializationUI, albo IClientChannel.DisplayInitializationUI (lub ich wersję asynchroniczną) przed otwarciem kanału (podejście jawne) lub wywołać pierwszą operację (podejście niejawne).

W przypadku korzystania z niejawnego podejścia aplikacja musi wywołać pierwszą operację na rozszerzeniu ClientBase<TChannel> lub IClientChannel. Jeśli wywołane zostanie coś innego niż pierwsza operacja, zostanie zgłoszony wyjątek.

W przypadku korzystania z jawnego podejścia aplikacja musi wykonać następujące kroki w następującej kolejności:

  1. Zadzwoń do ClientBase<TChannel>.DisplayInitializationUI lub IClientChannel.DisplayInitializationUI (lub wywołaj wersję asynchroniczną).

  2. Po zwróceniu inicjalizatorów wywołaj metodę Open na obiekcie IClientChannel albo na obiekcie IClientChannel, zwróconym z właściwości ClientBase<TChannel>.InnerChannel.

  3. Operacje połączeń

Zaleca się, aby aplikacje o jakości produkcyjnej kontrolowały procesy związane z interfejsem użytkownika, przyjmując podejście jawne.

Aplikacje korzystające z niejawnego podejścia wywołują inicjatory interfejsu użytkownika, ale jeśli użytkownik aplikacji nie odpowie w limicie czasu wysyłania powiązania, zgłaszany jest wyjątek po zwróceniu interfejsu użytkownika.

Zobacz także