ServiceBehaviorAttribute.ConcurrencyMode Egenskap
Definition
Viktigt
En del information gäller för förhandsversionen av en produkt och kan komma att ändras avsevärt innan produkten blir allmänt tillgänglig. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, avseende informationen som visas här.
Hämtar eller anger om en tjänst stöder en tråd, flera trådar eller återaktiveringsanrop.
public:
property System::ServiceModel::ConcurrencyMode ConcurrencyMode { System::ServiceModel::ConcurrencyMode get(); void set(System::ServiceModel::ConcurrencyMode value); };
public System.ServiceModel.ConcurrencyMode ConcurrencyMode { get; set; }
member this.ConcurrencyMode : System.ServiceModel.ConcurrencyMode with get, set
Public Property ConcurrencyMode As ConcurrencyMode
Egenskapsvärde
Ett av ConcurrencyMode värdena, standardvärdet är Single.
Undantag
Värdet är inte ett av ConcurrencyMode värdena.
Exempel
I följande kodexempel visas skillnaden mellan att använda Single, Reentrantoch Multiple. Det här exemplet kompileras inte utan en verklig implementering bakom det, men visar den typ av trådgarantier som Windows Communication Foundation (WCF) gör och vad det innebär för din åtgärdskod.
using System;
using System.ServiceModel;
[ServiceContract]
public interface IHttpFetcher
{
[OperationContract]
string GetWebPage(string address);
}
// These classes have the invariant that:
// this.slow.GetWebPage(this.cachedAddress) == this.cachedWebPage.
// When you read cached values you can assume they are valid. When
// you write the cached values, you must guarantee that they are valid.
// With ConcurrencyMode.Single, WCF does not call again into the object
// so long as the method is running. After the operation returns the object
// can be called again, so you must make sure state is consistent before
// returning.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
class SingleCachingHttpFetcher : IHttpFetcher
{
string cachedWebPage;
string cachedAddress;
readonly IHttpFetcher slow;
public string GetWebPage(string address)
{
// <-- Can assume cache is valid.
if (this.cachedAddress == address)
{
return this.cachedWebPage;
}
// <-- Cache is no longer valid because we are changing
// one of the values.
this.cachedAddress = address;
string webPage = slow.GetWebPage(address);
this.cachedWebPage = webPage;
// <-- Cache is valid again here.
return this.cachedWebPage;
// <-- Must guarantee that the cache is valid because we are returning.
}
}
// With ConcurrencyMode.Reentrant, WCF makes sure that only one
// thread runs in your code at a time. However, when you call out on a
// channel, the operation can get called again on another thread. Therefore
// you must confirm that state is consistent both before channel calls and
// before you return.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class ReentrantCachingHttpFetcher : IHttpFetcher
{
string cachedWebPage;
string cachedAddress;
readonly SlowHttpFetcher slow;
public ReentrantCachingHttpFetcher()
{
this.slow = new SlowHttpFetcher();
}
public string GetWebPage(string address)
{
// <-- Can assume that cache is valid.
if (this.cachedAddress == address)
{
return this.cachedWebPage;
}
// <-- Must guarantee that the cache is valid, because
// the operation can be called again before we return.
string webPage = slow.GetWebPage(address);
// <-- Can assume cache is valid.
// <-- Cache is no longer valid because we are changing
// one of the values.
this.cachedAddress = address;
this.cachedWebPage = webPage;
// <-- Cache is valid again here.
return this.cachedWebPage;
// <-- Must guarantee that cache is valid because we are returning.
}
}
// With ConcurrencyMode.Multiple, threads can call an operation at any time.
// It is your responsibility to guard your state with locks. If
// you always guarantee you leave state consistent when you leave
// the lock, you can assume it is valid when you enter the lock.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MultipleCachingHttpFetcher : IHttpFetcher
{
string cachedWebPage;
string cachedAddress;
readonly SlowHttpFetcher slow;
readonly object ThisLock = new object();
public MultipleCachingHttpFetcher()
{
this.slow = new SlowHttpFetcher();
}
public string GetWebPage(string address)
{
lock (this.ThisLock)
{
// <-- Can assume cache is valid.
if (this.cachedAddress == address)
{
return this.cachedWebPage;
// <-- Must guarantee that cache is valid because
// the operation returns and releases the lock.
}
// <-- Must guarantee that cache is valid here because
// the operation releases the lock.
}
string webPage = slow.GetWebPage(address);
lock (this.ThisLock)
{
// <-- Can assume cache is valid.
// <-- Cache is no longer valid because the operation
// changes one of the values.
this.cachedAddress = address;
this.cachedWebPage = webPage;
// <-- Cache is valid again here.
// <-- Must guarantee that cache is valid because
// the operation releases the lock.
}
return webPage;
}
}
Kommentarer
Den här egenskapen anger om en instans av en tjänst kan hantera en tråd eller flera trådar som körs samtidigt, och om den är enkeltrådad, om återaktivering stöds.
Note
Egenskapen ConcurrencyMode interagerar med vissa andra inställningar. Om värdet till exempel InstanceContextMode är inställt på Single resultatet kan tjänsten bara bearbeta ett meddelande i taget om du inte också anger ConcurrencyMode värdet till Multiple. Den här egenskapen ger också ett beteende i kombination med egenskapen ServiceContractAttribute.SessionMode . Mer information finns i Sessioner, Instancing och Concurrency.
Single Inställningen ConcurrencyMode instruerar systemet att begränsa instanser av tjänsten till en körningstråd i taget, vilket gör att du inte kan hantera trådproblem. Multiple Värdet innebär att tjänstobjekt kan köras av flera trådar samtidigt. I det här fallet måste du säkerställa trådsäkerheten.
Reentrant begränsar också åtkomsten till en enda tråd i taget. medan åtgärden bearbetas kan inget annat meddelande ange åtgärden. Om ett anrop till en annan tjänst lämnar under åtgärden förlorar det aktuella meddelandet låset på åtgärden, vilket är fritt att bearbeta andra meddelanden. När tjänstens utrop returneras återupprättas låset och det ursprungliga meddelandet kan fortsätta att bearbetas till dess slutsats eller tills ett annat anrop ut ur åtgärden inträffar.
Important
Även om Single begränsar instanser av tjänsten till en körningstråd i taget måste du också ange MaxConcurrentCalls 1 för att garantera att inga meddelanden inte är i ordning.
Dessutom är det ditt ansvar att lämna objekttillståndet konsekvent före pratbubblan och du måste bekräfta att åtgärdslokala data är giltiga efter pratbubblan. Observera att tjänstinstansen endast låss upp genom att anropa en annan tjänst via en WCF-kanal. I det här fallet kan den anropade tjänsten skicka den första tjänsten igen via ett återanrop. Om den första tjänsten inte är reentrant resulterar anropssekvensen i ett dödläge. Mer information finns i ConcurrencyMode.
Under ett utgående anrop från en bearbetningsåtgärd kan data som inte är lokala för åtgärden ändras. (Lokala tillståndsdata är garanterat giltiga när det ursprungliga meddelandet återupptar bearbetningen.) Innan ditt utgående samtal måste du därför se till att icke-lokala data är giltiga för andra inkommande samtal och återanvända icke-lokala data när det utgående samtalet returneras.
Följande pseudokod illustrerar det nödvändiga mönstret för lyckat stöd för återaktivering.
public void MyMethod()
{
this.SomeNonLocalDataState;
// Here you need to clean nonlocal state for other users
OutboundProxy proxy = new OutboundProxy();
int returnValue = proxy.CallOutOfOperation();
// Ensure that this.SomeNonLocalDataState is valid for continued use.
this.ModifyNonLocalState;
return returnValue;
}
Använda mönstret Begin/End asynkront anrop för ett utgående anrop när ConcurrencyMode is Reentrant utlöser ett undantag. Asynkrona utgående anrop kräver en åtgärd där ConcurrencyMode är Multiple, i vilket fall du måste hantera synkroniseringsproblem.
Om ett meddelande tas emot för en instans som bryter mot dess samtidighetsläge väntar meddelandet vanligtvis tills instansen är tillgänglig eller tills den överskrider tidsgränsen.
Om ConcurrencyMode är inställt på Single och ett reentrant-anrop blockeras i väntan på att instansen ska frigöras identifierar systemet dessutom dödläget och utlöser ett undantag.
Note
En InvalidOperationException genereras vid körning om ReleaseServiceInstanceOnTransactionComplete är true när ConcurrencyMode egenskapen är inställd på Single.
Observera att du uttryckligen måste ange ReleaseServiceInstanceOnTransactionComplete till false om det finns en åtgärd med OperationBehaviorAttribute.TransactionScopeRequired värdet true och du anger ConcurrencyMode till Reentrant. Annars genereras ett verifieringsfel eftersom standardvärdet ReleaseServiceInstanceOnTransactionComplete för är true.
Det finns en interaktion mellan och ConcurrencyMode andra egenskaper som kan ändra körningsbeteendet. En fullständig beskrivning av dessa interaktioner finns i Sessioner, Instancing och Concurrency.