簡體   English   中英

WCF是否在多個線程上運行會話?

[英]Does WCF Run the session on more than one thread?

我有一個wcf服務(托管在IIS中),該服務設置為使用session 似乎有效。 調用Application_PostAcquireRequestState ,我有一個會話ID。

我最終以這種方式使用了它(在我的Global.asax中):

if (Context.Handler is IRequiresSessionState)
{
    log4net.ThreadContext.Properties["sessionId"] = Session.SessionID;
}

這似乎很好。 該值存儲在我的log4net屬性中。

但是,當我的服務操作開始時(我的實際WCF服務代碼),log4net屬性再次為null。

由於屬性是按線程存儲的( ThreadContext ),因此我只能假定這意味着在一個線程上建立會話,然后在另一個線程上執行會話。 我對嗎?

無論如何,是否有必要在正確的線程上設置我的log4net屬性(而不必記住在每個服務操作開始時進行上述調用)?

是的,IIS可能使用多個線程來服務多個WCF請求。 有關更多詳細信息,請參見http://msdn.microsoft.com/zh-cn/library/cc512374.aspx

您可能考慮為每個WCF請求使用記錄器的不同實例。

在多種情況下,WCF可能會更改您的線程:

  1. 不能保證將Global.asx線程用於服務調用(實際上不太可能)。
  2. 如果在同一會話期間有多個調用,則線程也可能在對同一服務實例的調用之間改變。

從理論上講,此類狀態信息應存儲在“操作上下文”對象中。 但是,由於log4net使用線程本地存儲,因此它成為一個尷尬的解決方案。

無論如何,是否有必要在正確的線程上設置我的log4net屬性(而不必記住在每個服務操作開始時進行上述調用)?

是。 創建一個自定義IOperationInvoker 我知道的最好的例子是Carlos Figueira的博客 如果將此作為服務行為應用,則應始終為服務代碼定義log4net屬性。

一個警告: 添加到線程本地存儲時,請確保清理。 這就是為什么log4net.ThreadContext.Stacks []。Push()返回IDisposable的原因。 換句話說,您的Invoke方法應如下所示(未完成且未經測試):

public object Invoke(object instance, object[] inputs, out object[] outputs)
{
    using (log4net.ThreadContext.Stacks[key].Push(value))
    {
        return this.originalInvoker.Invoke(instance, inputs, out outputs);
    }
}

請參閱Carlos的博客,以了解為什么要調用“ originalInvoker”。 請注意,如果要支持異步操作,則需要實現其他方法。

自定義屬性不必是字符串。 因此,您可以在全局上下文中存儲以下類的實例:

public class SessionIdProperty 
{
    public override string ToString()
    {
        // error handling omitted
        return Session.SessionID;
    }
}

這樣,log4net在記錄消息時可以直接訪問Session對象。 Log4net在非字符串屬性上調用ToString()方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM