ConcurrencyMode 枚举
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
指定服务类是支持单线程还是多线程操作模式。
public enum class ConcurrencyMode
public enum ConcurrencyMode
type ConcurrencyMode =
Public Enum ConcurrencyMode
- 继承
字段
Multiple | 2 | 服务实例是多线程的。 无同步保证。 因为其他线程可以随时更改服务对象,所以必须始终处理同步与状态一致性。 |
Reentrant | 1 | 服务实例是单线程的,且接受可重入调用。 可重入服务接受在调用其他服务的同时进行调用;因此在调出之前,您需要负责让对象的状态一致,而在调出之后,必须确认本地操作数据有效。 请注意,只有通过 WCF 通道调用其他服务,才能解锁服务实例。 在此情况下,已调用的服务可以通过回调重入第一个服务。 如果第一个服务不可重入,则该调用顺序会导致死锁。 有关详细信息,请参阅 ConcurrencyMode。 |
Single | 0 | 服务实例是单线程的,且不接受可重入调用。 如果 InstanceContextMode 属性为 Single,且其他消息在实例处理调用的同时到达,则这些消息必须等待,直到服务可用或消息超时为止。 |
示例
下面的代码示例演示了使用 Single、Reentrant 和 Multiple 之间的差异。 此示例不会在没有实际实现的情况下进行编译,但确实演示了 WCF 做出的线程保证的类型以及操作代码的含义。
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;
}
}
注解
ConcurrencyMode 与 ConcurrencyMode 属性一起使用,可指定服务类是支持单线程还是多线程操作模式。 单线程操作可以是可重入操作,也可以是不可重入操作。
下表显示了何时Windows Communication Foundation (WCF) 允许在另一个操作正在进行时调用,具体取决于该ConcurrencyMode操作。
ConcurrencyMode 值 | 是否允许调用新操作? |
---|---|
Single | 从不。 |
折返 | 仅在调用其他服务或回调时。 |
多种 | 始终。 |