Okres istnienia niestandardowy
W przykładzie Lifetime pokazano, jak napisać rozszerzenie programu Windows Communication Foundation (WCF) w celu zapewnienia niestandardowych usług okresu istnienia dla udostępnionych wystąpień usługi WCF.
Uwaga
Procedura instalacji i instrukcje kompilacji dla tego przykładu znajdują się na końcu tego artykułu.
Udostępnianie instancingu
Program WCF oferuje kilka trybów stancingu dla wystąpień usługi. Tryb udostępniania instancingu opisany w tym artykule umożliwia udostępnianie wystąpienia usługi między wieloma kanałami. Klienci mogą skontaktować się z metodą fabryki w usłudze i utworzyć nowy kanał w celu rozpoczęcia komunikacji. Poniższy fragment kodu pokazuje, jak aplikacja kliencka tworzy nowy kanał do istniejącego wystąpienia usługi:
// Create a header for the shared instance id
MessageHeader shareableInstanceContextHeader = MessageHeader.CreateHeader(
CustomHeader.HeaderName,
CustomHeader.HeaderNamespace,
Guid.NewGuid().ToString());
// Create the channel factory
ChannelFactory<IEchoService> channelFactory =
new ChannelFactory<IEchoService>("echoservice");
// Create the first channel
IEchoService proxy = channelFactory.CreateChannel();
// Call an operation to create shared service instance
using (new OperationContextScope((IClientChannel)proxy))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy.Echo("Apple"));
}
((IChannel)proxy).Close();
// Create the second channel
IEchoService proxy2 = channelFactory.CreateChannel();
// Call an operation using the same header that will reuse the shared service instance
using (new OperationContextScope((IClientChannel)proxy2))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy2.Echo("Apple"));
}
W przeciwieństwie do innych trybów stancing, udostępniony tryb stancing ma unikatowy sposób zwalniania wystąpień usługi. Domyślnie, gdy wszystkie kanały są zamykane dla InstanceContextprogramu , środowisko uruchomieniowe usługi WCF sprawdza, czy usługa InstanceContextMode jest skonfigurowana na PerCall wartość lub PerSession, a jeśli tak, zwalnia wystąpienie i oświadczenia zasobów. Jeśli jest używany niestandardowy IInstanceContextProvider , program WCF wywołuje IsIdle metodę implementacji dostawcy przed udostępnieniem wystąpienia. Jeśli IsIdle zwraca true
wystąpienie jest zwalniane, w przeciwnym razie IInstanceContextProvider implementacja jest odpowiedzialna za powiadamianie Dispatcher
o stanie bezczynności przy użyciu metody wywołania zwrotnego. Odbywa się to przez wywołanie NotifyIdle metody dostawcy.
W tym przykładzie pokazano, jak można opóźnić zwolnienie InstanceContext elementu z limitem czasu bezczynności przez 20 sekund.
Rozszerzanie obiektu InstanceContext
W programie WCF InstanceContext jest połączeniem między wystąpieniem usługi a elementem Dispatcher
. Program WCF umożliwia rozszerzenie tego składnika środowiska uruchomieniowego przez dodanie nowego stanu lub zachowania przy użyciu rozszerzalnego wzorca obiektu. Rozszerzalny wzorzec obiektu jest używany w programie WCF do rozszerzania istniejących klas środowiska uruchomieniowego o nowe funkcje lub dodawania nowych funkcji stanu do obiektu. Istnieją trzy interfejsy w rozszerzalnym wzorcu obiektu: IExtensibleObject<T>, IExtension<T>i IExtensionCollection<T>.
Interfejs IExtensibleObject<T> jest implementowany przez obiekty, aby umożliwić rozszerzenia, które dostosują ich funkcjonalność.
Interfejs IExtension<T> jest implementowany przez obiekty, które mogą być rozszerzeniami klas typu T
.
I wreszcie, interfejs jest kolekcją IExtension<T> implementacji, IExtensionCollection<T> która umożliwia pobieranie implementacji IExtension<T> według ich typu.
W związku z tym, aby rozszerzyć element InstanceContext, należy zaimplementować IExtension<T> interfejs. W tym przykładowym projekcie CustomLeaseExtension
klasa zawiera tę implementację.
class CustomLeaseExtension : IExtension<InstanceContext>
{
}
Interfejs IExtension<T> ma dwie metody Attach i Detach. Jak implikują ich nazwy, te dwie metody są wywoływane, gdy środowisko uruchomieniowe dołącza i odłącza rozszerzenie do wystąpienia InstanceContext klasy. W tym przykładzie Attach
metoda służy do śledzenia InstanceContext obiektu należącego do bieżącego wystąpienia rozszerzenia.
InstanceContext owner;
public void Attach(InstanceContext owner)
{
this.owner = owner;
}
Ponadto należy dodać niezbędną implementację do rozszerzenia, aby zapewnić obsługę rozszerzonego okresu istnienia. ICustomLease
W związku z tym interfejs jest deklarowany przy użyciu żądanych metod i jest implementowany w CustomLeaseExtension
klasie .
interface ICustomLease
{
bool IsIdle { get; }
InstanceContextIdleCallback Callback { get; set; }
}
class CustomLeaseExtension : IExtension<InstanceContext>, ICustomLease
{
}
Gdy program WCF wywołuje metodę IsIdle w implementacjiIInstanceContextProvider, to wywołanie jest kierowane do IsIdle metody .CustomLeaseExtension
Następnie funkcja CustomLeaseExtension
sprawdza stan prywatny, aby sprawdzić, czy InstanceContext stan jest bezczynny. Jeśli jest bezczynny, zwraca wartość true
. W przeciwnym razie uruchamia czasomierz dla określonej ilości rozszerzonego okresu istnienia.
public bool IsIdle
{
get
{
lock (thisLock)
{
if (isIdle)
{
return true;
}
else
{
StartTimer();
return false;
}
}
}
}
W zdarzeniu czasomierza Elapsed
funkcja wywołania zwrotnego w dyspozytorze jest wywoływana w celu uruchomienia innego cyklu oczyszczania.
void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
{
lock (thisLock)
{
StopTimer();
isIdle = true;
Utility.WriteMessageToConsole(
ResourceHelper.GetString("MsgLeaseExpired"));
callback(owner);
}
}
Nie ma możliwości odnowienia czasomierza uruchomionego po nadejściu nowego komunikatu dla wystąpienia przeniesionego do stanu bezczynności.
Przykład implementuje przechwytywanie IInstanceContextProvider wywołań IsIdle metody i kierowanie ich do CustomLeaseExtension
metody . Implementacja jest zawarta IInstanceContextProvider w CustomLifetimeLease
klasie . Metoda IsIdle jest wywoływana, gdy program WCF ma zwolnić wystąpienie usługi. Jednak w kolekcji ServiceBehavior IInstanceContextProvider istnieje tylko jedno wystąpienie określonej ISharedSessionInstance
implementacji. Oznacza to, że nie ma możliwości sprawdzenia, czy InstanceContext element jest zamknięty w czasie sprawdzania metody przez usługę IsIdle WCF. W związku z tym w tym przykładzie użyto blokowania wątków w celu serializacji żądań do IsIdle metody .
Ważne
Używanie blokowania wątków nie jest zalecanym podejściem, ponieważ serializacja może poważnie wpłynąć na wydajność aplikacji.
Prywatne pole składowe jest używane w CustomLifetimeLease
klasie do śledzenia stanu bezczynności i jest zwracane przez metodę IsIdle . Za każdym razem, gdy metoda jest wywoływana IsIdle , isIdle
pole jest zwracane i resetowane do false
. Należy ustawić tę wartość false
na , aby upewnić się, że dyspozytor wywołuje metodę NotifyIdle .
public bool IsIdle(InstanceContext instanceContext)
{
get
{
lock (thisLock)
{
//...
bool idleCopy = isIdle;
isIdle = false;
return idleCopy;
}
}
}
IInstanceContextProvider.IsIdle Jeśli metoda zwróci false
metodę , dyspozytor rejestruje funkcję wywołania zwrotnego przy użyciu NotifyIdle metody . Ta metoda odbiera odwołanie do InstanceContext zwalnianego. W związku z tym przykładowy kod może wykonywać zapytania dotyczące ICustomLease
rozszerzenia typu i sprawdzać ICustomLease.IsIdle
właściwość w stanie rozszerzonym.
public void NotifyIdle(InstanceContextIdleCallback callback,
InstanceContext instanceContext)
{
lock (thisLock)
{
ICustomLease customLease =
instanceContext.Extensions.Find<ICustomLease>();
customLease.Callback = callback;
isIdle = customLease.IsIdle;
if (isIdle)
{
callback(instanceContext);
}
}
}
Przed sprawdzeniem ICustomLease.IsIdle
właściwości należy ustawić właściwość Wywołanie zwrotne, ponieważ jest to niezbędne do CustomLeaseExtension
powiadamiania dyspozytora, gdy stanie się bezczynny. Jeśli ICustomLease.IsIdle
zwraca true
wartość isIdle
, prywatny element członkowski jest po prostu ustawiony CustomLifetimeLease
na true
wartość i wywołuje metodę wywołania zwrotnego. Ponieważ kod przechowuje blokadę, inne wątki nie mogą zmieniać wartości tego prywatnego elementu członkowskiego. A następnym razem, gdy dyspozytor wywołuje metodę IInstanceContextProvider.IsIdle, zwraca true
i pozwala usłudze Dispatcher zwolnić wystąpienie.
Po zakończeniu prac związanych z rozszerzeniem niestandardowym należy podłączyć go do modelu usługi. Aby podłączyć implementację CustomLeaseExtension
do InstanceContextprogramu , program WCF udostępnia IInstanceContextInitializer interfejs umożliwiający wykonanie rozruchu InstanceContextelementu . W przykładzie CustomLeaseInitializer
klasa implementuje ten interfejs i dodaje wystąpienie CustomLeaseExtension
do Extensions kolekcji z jedynej inicjalizacji metody. Ta metoda jest wywoływana przez dyspozytor podczas inicjowania metody InstanceContext.
public void InitializeInstanceContext(InstanceContext instanceContext,
System.ServiceModel.Channels.Message message, IContextChannel channel)
//...
IExtension<InstanceContext> customLeaseExtension =
new CustomLeaseExtension(timeout, headerId);
instanceContext.Extensions.Add(customLeaseExtension);
}
Na koniec implementacja IInstanceContextProvider jest podłączona do modelu usługi przy użyciu implementacji IServiceBehavior . Ta implementacja jest umieszczana w klasie, a także pochodzi z klasy bazowej CustomLeaseTimeAttribute
Attribute , aby uwidocznić to zachowanie jako atrybut.
public void ApplyDispatchBehavior(ServiceDescription description,
ServiceHostBase serviceHostBase)
{
CustomLifetimeLease customLease = new CustomLifetimeLease(timeout);
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceContextProvider = customLease;
}
}
}
}
To zachowanie można dodać do przykładowej klasy usługi, dodając do niej adnotacje za pomocą atrybutu CustomLeaseTime
.
[CustomLeaseTime(Timeout = 20000)]
public class EchoService : IEchoService
{
//…
}
Po uruchomieniu przykładu żądania operacji i odpowiedzi są wyświetlane w oknach konsoli usługi i klienta. Naciśnij klawisz ENTER w każdym oknie konsoli, aby zamknąć usługę i klienta.
Aby skonfigurować, skompilować i uruchomić przykład
Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.
Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).
Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.