HttpTransportElement的RequestInitializationTimeout是什么? MSDN说:
“请求初始化”到底是什么?为什么要设置此属性?
最佳答案
没有关于 RequestInitializationTimeout
的明确文档。
SharedHttpTransportManager.IsCompatible
的源代码中有一个有关RequestInitializationTimeout
检查的注释:
如果检查分配给 TimeoutException
内传递的requestException
的 HttpRequestContext.SetMessage(message, requestException)
的 OnParseComplete
,我们可以看到:
new TimeoutException(SR.GetString(
SR.RequestInitializationTimeoutReached,
this.HttpRequestContext.Listener.RequestInitializationTimeout,
"RequestInitializationTimeout",
typeof(HttpTransportBindingElement).Name))
并且有关
SR.RequestInitializationTimeoutReached
System.Private.ServiceModel
异常消息是:The initialization process of the request message timed out after {0}. To increase this quota, use the '{1}' property on the '{2}'.
将会被格式化为如下形式:
The initialization process of the request message timed out after 00:00:10. To increase this quota, use the 'RequestInitializationTimeout' property on the 'HttpTransportBindingElement'.
tl; dr
如果遵循源代码,则可以在
EmptyHttpPipeline
中找到它的用法。在 build 者default
EmptyHttpPipeline.EmptyHttpPipeline
如果存在
RequestInitializationTimeout
TimeSpan
(而不是禁用它的 00:00:00
),则设置 IOThreadTimer
,并将dueTime
设置为TimeSpan
滴答声,将 OnRequestInitializationTimeout
Action
回调和this
(实际的EmptyHttpPipeline
对象)作为callbackState
。if (this.httpRequestContext.Listener.RequestInitializationTimeout != HttpTransportDefaults.RequestInitializationTimeout)
{
this.requestInitializationTimer = new IOThreadTimer(onRequestInitializationTimeout, this, false);
this.requestInitializationTimer.Set(this.httpRequestContext.Listener.RequestInitializationTimeout);
}
什么时候检查?
通过尝试取消
EmptyHttpPipeline.OnParseComplete
来检查何时调用 requestInitializationTimer
方法。如果有一个计时器,并且之前已被取消或过期,它将创建一个TimeoutException
,它分配给requestException
,并与HttpPipeline.HttpRequestContext.SetMessage
一起传递给message
:protected override void OnParseComplete(Message message, Exception requestException)
{
if (!this.CancelRequestInitializationTimer() && requestException == null)
{
requestException = FxTrace.Exception.AsError(new TimeoutException(SR.GetString(
SR.RequestInitializationTimeoutReached,
this.HttpRequestContext.Listener.RequestInitializationTimeout,
"RequestInitializationTimeout",
typeof(HttpTransportBindingElement).Name)));
}
this.HttpRequestContext.SetMessage(message, requestException);
}
正在使用
OnParseComplete
方法中的 EnqueueMessageAsyncResult.CompleteParseAndEnqueue
HandleParseIncomingMessage
在 AsyncCallback
内部调用 EnqueueMessageAsyncResult.End
方法。 EnqueueMessageAsyncResult
对象是在调用 EmptyHttpPipeline.BeginProcessInboundRequest
时创建的,它在 EmptyHttpPipeline.EndProcessInboundRequest
内部终止。BeginProcessInboundRequest
和 EndProcessInboundRequest
internal override IAsyncResult BeginProcessInboundRequest(
ReplyChannelAcceptor replyChannelAcceptor,
Action dequeuedCallback,
AsyncCallback callback,
object state)
{
this.TraceBeginProcessInboundRequestStart();
return new EnqueueMessageAsyncResult(replyChannelAcceptor, dequeuedCallback, this, callback, state);
}
internal override void EndProcessInboundRequest(IAsyncResult result)
{
// It will trigger HandleParseIncomingMessage AsyncCallback,
// that will call CompleteParseAndEnqueue
EnqueueMessageAsyncResult.End(result);
this.TraceProcessInboundRequestStop();
}
EnqueueMessageAsyncResult.CompleteParseAndEnqueue
void CompleteParseAndEnqueue(IAsyncResult result)
{
using (DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.BoundOperation(this.CallbackActivity) : null)
{
Exception requestException;
Message message = this.pipeline.EndParseIncomingMesssage(result, out requestException);
if ((message == null) && (requestException == null))
{
throw FxTrace.Exception.AsError(
new ProtocolException(
SR.GetString(SR.MessageXmlProtocolError),
new XmlException(SR.GetString(SR.MessageIsEmpty))));
}
// Here the EmptyHttpPipeline.OnParseComplete is being invoked
this.pipeline.OnParseComplete(message, requestException);
this.acceptor.Enqueue(this.pipeline.HttpRequestContext, this.dequeuedCallback, true);
}
}
如何检查和取消?
正在使用
CancelRequestInitializationTimer
方法检查它,如果没有设置计时器,它只会返回true;否则,它会返回true。如果先前已取消,则返回false,否则调用IOThreadTimer.Cancel
方法进行检查,如果已取消,则返回true;如果计时器过期,则返回false。EmptyHttpPipeline.CancelRequestInitializationTimer
protected bool CancelRequestInitializationTimer()
{
if (this.requestInitializationTimer == null)
{
return true;
}
if (this.requestInitializationTimerCancelled)
{
return false;
}
bool result = this.requestInitializationTimer.Cancel();
this.requestInitializationTimerCancelled = true;
return result;
}
实际取消了什么?
在
OnRequestInitializationTimeout
方法内部,我们可以看到它取消了HttpPipeline
,从而中止了 HttpPipeline.httpRequestContext
:EmptyHttpPipeline.OnRequestInitializationTimeout
static void OnRequestInitializationTimeout(object obj)
{
Fx.Assert(obj != null, "obj should not be null.");
HttpPipeline thisPtr = (HttpPipeline)obj;
thisPtr.Cancel();
}
HttpPipeline.Cancel
public virtual void Cancel()
{
this.httpRequestContext.Abort();
}
我们什么时候得到
EmptyHttpPipeline
对象?如果我们使用接受
EmptyHttpPipeline
且不存在 transportIntegrationHandler = null
的静态 HttpPipeline.CreateHttpPipeline
设置TransportIntegrationHandler
,则会得到 HttpRequestContext.HttpMessagesSupported
:public static HttpPipeline CreateHttpPipeline(HttpRequestContext httpRequestContext, TransportIntegrationHandler transportIntegrationHandler, bool isWebSocketTransport)
{
if (transportIntegrationHandler == null)
{
Fx.Assert(!isWebSocketTransport, "isWebSocketTransport should be false if there's no HTTP message handler existing.");
if (httpRequestContext.HttpMessagesSupported)
{
return new HttpMessageSupportedHttpPipeline(httpRequestContext);
}
return new EmptyHttpPipeline(httpRequestContext);
}
return NormalHttpPipeline.CreatePipeline(httpRequestContext, transportIntegrationHandler, isWebSocketTransport);
}
在
CreateHttpPipeline
上调用 HttpRequestContext.InitializeHttpPipeline
:HttpRequestContext.InitializeHttpPipeline
public void InitializeHttpPipeline(TransportIntegrationHandler transportIntegrationHandler)
{
this.httpPipeline = HttpPipeline.CreateHttpPipeline(this, transportIntegrationHandler, this.IsWebSocketRequest);
}
使用
HttpRequestContext requestContext
在 HttpContextReceivedAsyncResult
内的 HttpContextReceivedAsyncResult<TListenerChannel>.ProcessHttpContextAsync
(传入 HttpChannelListener<TListenerChannel>.transportIntegrationHandler
构造函数中)中调用ojit_a
AsyncCompletionResult ProcessHttpContextAsync()
{
bool abort = false;
try
{
this.context.InitializeHttpPipeline(this.listener.transportIntegrationHandler);
...
}
...
}
结论
所有这些使我们得出以下结论:当创建的
HttpContextReceivedAsyncResult<TListenerChannel>.ProcessHttpContextAsync
没有HttpPipeline
并且没有TransportIntegrationHandler
的HttpMessagesSupported
时,新的HttpRequestContext
对象将对EmptyHttpPipeline
/ RequestInitializationTimeout
设置超时(如果设置了BeginProcessInboundRequest
),并在设置消息时设置异常在EndProcessInboundRequest
中使用EmptyHttpPipeline.HttpRequestContext.SetMessage
。关于.net - 为什么要设置RequestInitializationTimeout属性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30900894/