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并且没有TransportIntegrationHandlerHttpMessagesSupported时,新的HttpRequestContext对象将对EmptyHttpPipeline / RequestInitializationTimeout设置超时(如果设置了BeginProcessInboundRequest),并在设置消息时设置异常在EndProcessInboundRequest中使用EmptyHttpPipeline.HttpRequestContext.SetMessage

关于.net - 为什么要设置RequestInitializationTimeout属性?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30900894/

10-08 23:37