12,162
社区成员
发帖
与我相关
我的任务
分享
namespace System.ServiceModel.Dispatcher
{
using System;
using System.ServiceModel;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Runtime.Serialization;
interface ISessionThrottleNotification
{
void ThrottleAcquired();
}
public sealed class ServiceThrottle
{
internal const int DefaultMaxConcurrentCalls = 16;
internal const int DefaultMaxConcurrentSessions = 10;
FlowThrottle calls;
FlowThrottle sessions;
QuotaThrottle dynamic;
FlowThrottle instanceContexts;
ServiceHostBase host;
bool isActive;
object thisLock = new object();
internal ServiceThrottle(ServiceHostBase host)
{
if (!((host != null)))
{
DiagnosticUtility.DebugAssert("ServiceThrottle.ServiceThrottle: (host != null)");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("host");
}
this.host = host;
this.MaxConcurrentCalls = ServiceThrottle.DefaultMaxConcurrentCalls;
this.MaxConcurrentSessions = ServiceThrottle.DefaultMaxConcurrentSessions;
this.isActive = true;
}
FlowThrottle Calls
{
get
{
lock (this.ThisLock)
{
if (this.calls == null)
{
this.calls = new FlowThrottle(this.GotCall, ServiceThrottle.DefaultMaxConcurrentCalls,
ServiceThrottle.MaxConcurrentCallsPropertyName, ServiceThrottle.MaxConcurrentCallsConfigName);
}
return this.calls;
}
}
}
FlowThrottle Sessions
{
get
{
lock (this.ThisLock)
{
if (this.sessions == null)
{
this.sessions = new FlowThrottle(this.GotSession, ServiceThrottle.DefaultMaxConcurrentSessions,
ServiceThrottle.MaxConcurrentSessionsPropertyName, ServiceThrottle.MaxConcurrentSessionsConfigName);
}
return this.sessions;
}
}
}
QuotaThrottle Dynamic
{
get
{
lock (this.ThisLock)
{
if (this.dynamic == null)
{
this.dynamic = new QuotaThrottle(this.GotDynamic, new object());
this.dynamic.Owner = "ServiceHost";
}
this.UpdateIsActive();
return this.dynamic;
}
}
}
internal int ManualFlowControlLimit
{
get { return this.Dynamic.Limit; }
set { this.Dynamic.SetLimit(value); }
}
const string MaxConcurrentCallsPropertyName = "MaxConcurrentCalls";
const string MaxConcurrentCallsConfigName = "maxConcurrentCalls";
public int MaxConcurrentCalls
{
get { return this.Calls.Capacity; }
set
{
this.ThrowIfClosedOrOpened(MaxConcurrentCallsPropertyName);
this.Calls.Capacity = value;
this.UpdateIsActive();
}
}
const string MaxConcurrentSessionsPropertyName = "MaxConcurrentSessions";
const string MaxConcurrentSessionsConfigName = "maxConcurrentSessions";
public int MaxConcurrentSessions
{
get { return this.Sessions.Capacity; }
set
{
this.ThrowIfClosedOrOpened(MaxConcurrentSessionsPropertyName);
this.Sessions.Capacity = value;
this.UpdateIsActive();
}
}
const string MaxConcurrentInstancesPropertyName = "MaxConcurrentInstances";
const string MaxConcurrentInstancesConfigName = "maxConcurrentInstances";
public int MaxConcurrentInstances
{
get { return this.InstanceContexts.Capacity; }
set
{
this.ThrowIfClosedOrOpened(MaxConcurrentInstancesPropertyName);
this.InstanceContexts.Capacity = value;
this.UpdateIsActive();
}
}
FlowThrottle InstanceContexts
{
get
{
lock (this.ThisLock)
{
if (this.instanceContexts == null)
{
this.instanceContexts = new FlowThrottle(this.GotInstanceContext, Int32.MaxValue,
ServiceThrottle.MaxConcurrentInstancesPropertyName, ServiceThrottle.MaxConcurrentInstancesConfigName);
}
return this.instanceContexts;
}
}
}
internal bool IsActive
{
get { return this.isActive; }
}
internal object ThisLock
{
get { return this.thisLock; }
}
bool PrivateAcquireCall(ChannelHandler channel)
{
return (this.calls == null) || this.calls.Acquire(channel);
}
bool PrivateAcquireSessionListenerHandler(ListenerHandler listener)
{
if ((this.sessions != null) && (listener.Channel != null) && (listener.Channel.Throttle == null))
{
listener.Channel.Throttle = this;
return this.sessions.Acquire(listener);
}
else
{
return true;
}
}
bool PrivateAcquireSession(ISessionThrottleNotification source)
{
return (this.sessions == null || this.sessions.Acquire(source));
}
bool PrivateAcquireDynamic(ChannelHandler channel)
{
return (this.dynamic == null) || this.dynamic.Acquire(channel);
}
bool PrivateAcquireInstanceContext(ChannelHandler channel)
{
if ((this.instanceContexts != null) && (channel.InstanceContext == null))
{
channel.InstanceContextServiceThrottle = this;
return this.instanceContexts.Acquire(channel);
}
else
{
return true;
}
}
internal bool AcquireCall(ChannelHandler channel)
{
lock (this.ThisLock)
{
return (this.PrivateAcquireCall(channel));
}
}
internal bool AcquireInstanceContextAndDynamic(ChannelHandler channel, boolacquireInstanceContextThrottle)
{
lock(this.ThisLock)
{
if (!acquireInstanceContextThrottle)
{
return this.PrivateAcquireDynamic(channel);
}
else
{
return (this.PrivateAcquireInstanceContext(channel) &&
this.PrivateAcquireDynamic(channel));
}
}
}
internal bool AcquireSession(ISessionThrottleNotification source)
{
lock (this.ThisLock)
{
return this.PrivateAcquireSession(source);
}
}
internal bool AcquireSession(ListenerHandler listener)
{
lock (this.ThisLock)
{
return this.PrivateAcquireSessionListenerHandler(listener);
}
}
void GotCall(object state)
{
ChannelHandler channel = (ChannelHandler)state;
lock (this.ThisLock)
{
channel.ThrottleAcquiredForCall();
}
}
void GotDynamic(object state)
{
((ChannelHandler)state).ThrottleAcquired();
}
void GotInstanceContext(object state)
{
ChannelHandler channel = (ChannelHandler)state;
lock (this.ThisLock)
{
if (this.PrivateAcquireDynamic(channel))
channel.ThrottleAcquired();
}
}
void GotSession(object state)
{
((ISessionThrottleNotification)state).ThrottleAcquired();
}
internal void DeactivateChannel()
{
if (this.isActive)
{
if (this.sessions != null)
this.sessions.Release();
}
}
internal void DeactivateCall()
{
if (this.isActive)
{
if (this.calls != null)
this.calls.Release();
}
}
internal void DeactivateInstanceContext()
{
if (this.isActive)
{
if (this.instanceContexts != null)
{
this.instanceContexts.Release();
}
}
}
internal int IncrementManualFlowControlLimit(int incrementBy)
{
return this.Dynamic.IncrementLimit(incrementBy);
}
void ThrowIfClosedOrOpened(string memberName)
{
if (this.host.State == CommunicationState.Opened)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(newInvalidOperationException(SR.GetString(SR.SFxImmutableThrottle1, memberName)));
}
else
{
this.host.ThrowIfClosedOrOpened();
}
}
void UpdateIsActive()
{
this.isActive = ((this.dynamic != null) ||
((this.calls != null) && (this.calls.Capacity != Int32.MaxValue)) ||
((this.sessions != null) && (this.sessions.Capacity != Int32.MaxValue)) ||
((this.instanceContexts != null) && (this.instanceContexts.Capacity != Int32.MaxValue)));
}
}
}
namespace System.ServiceModel.Dispatcher
{
using System;
using System.Diagnostics;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.Collections.Generic;
using System.Threading;
sealed class FlowThrottle
{
int capacity;
int count;
object mutex;
WaitCallback release;
Queue<object> waiters;
String propertyName;
String configName;
internal FlowThrottle(WaitCallback release, int capacity, String propertyName, String configName)
{
if (capacity <= 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxThrottleLimitMustBeGreaterThanZero0)));
this.count = 0;
this.capacity = capacity;
this.mutex = new object();
this.release = release;
this.waiters = new Queue<object>();
this.propertyName = propertyName;
this.configName = configName;
}
internal int Capacity
{
get { return this.capacity; }
set
{
if (value <= 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxThrottleLimitMustBeGreaterThanZero0)));
this.capacity = value;
}
}
internal bool Acquire(object o)
{
lock (this.mutex)
{
if (this.count < this.capacity)
{
this.count++;
return true;
}
else
{
if (this.waiters.Count == 0)
{
if (DiagnosticUtility.ShouldTraceInformation)
{
DiagnosticUtility.DiagnosticTrace.TraceEvent(
TraceEventType.Information,
TraceCode.ServiceThrottleLimitReached,
SR.GetString(SR.TraceCodeServiceThrottleLimitReached,
this.propertyName, this.capacity, this.configName));
}
}
this.waiters.Enqueue(o);
return false;
}
}
}
internal void Release()
{
object next = null;
lock (this.mutex)
{
if (this.waiters.Count > 0)
{
next = this.waiters.Dequeue();
if (this.waiters.Count == 0)
this.waiters.TrimExcess();
}
else
{
this.count--;
}
}
if (next != null)
this.release(next);
}
}