簡體   English   中英

為什么asp.net用戶會話結束會導致另一個應用程序池中的Quartz任務終止?

[英]Why does an asp.net user session ending cause a Quartz task in a different app pool to terminate?

我在asp.net應用程序中使用C#和Quartz調度程序。 用戶單擊前端的按鈕后,Quartz任務會立即在后台運行,但是當用戶會話結束時,任務會過早終止。

用戶會話是與Quartz會話運行的應用程序池不同的應用程序池。

顯然,即使啟動任務的用戶退出或其會話結束,所需的行為也是為了使任務繼續。

更新:我添加了更多日志記錄信息 - 實際上導致任務停止的是:

位於System.Web.Hosting.HostingEnvironment.InitiateShutdownWorkItemCallback(對象狀態)的System.Web.Hosting.HostingEnvironment.StopRegisteredObjects(布爾值立即),位於System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)at at System.Threading.ThreadPoolWorkQueue.Dispatch()上的System.Threading.QuereadingUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()中的System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回調,Object狀態,Boolean preserveSyncCtx)

運行Quartz任務的任務調度程序類已在System.Web.Hosting.HostingEnvironment中注冊 - 並且在調度線程時,它看起來像是停止任務調度程序。 所以這可能更接近我應該看的地方 - 我需要理解為什么運行任務的線程被調度。


最初我認為問題與組件的Autofac Lifetime范圍有關,而我的問題最初集中在那個問題上。 我將在下面留下我的Autofac評論,因為可能會發現這是一個因素,在我解決問題之前我還不知道。

問題的原始描述:我正在研究一個問題,即組件的生命周期范圍錯誤地表現為請求生命周期范圍。

因為我認為如果我在調試器中檢查Autofac內部代碼有很多依賴關系,它會幫助我找出導致問題的原因。

但是,我發現很難理解Autofac內部如何表示生命周期范圍。

有誰知道如何找到與Autofac中的組件關聯的生命周期范圍 - 特別是如果它有請求生命周期范圍?

我有點得到你正在尋找的東西,但我不確定知道生命范圍如何“內部”起作用將會有所幫助。 也許只是明確范圍如何在概念上工作以及父范圍如何與子范圍相關將有所幫助。 圍繞這個有一個文檔的looooot。

如果您真的想知道生活范圍是如何“在內部表示”的,那么您最好的選擇是查看來源。 ContainerBuilder.Build開始,它創建一個新的Container (它本身有一個范圍 - “根壽命范圍”)。 然后看看LifetimeScope如何工作,從注冊表中解析組件。

但是,就像我說的那樣,我認為這不會像概念那樣對你有所幫助。

如果沒有最小,完整和可驗證的例子,我無法告訴你哪里出錯了; 並且沒有任何錯誤消息表明我們可以開始提供任何幫助; 但我猜的是:

  • 您的應用啟動並構建容器。
  • 后台任務基於從容器中解析的內容開始 (可能不好,因為這可能導致一次性組件的內存泄漏 )或者從子范圍啟動。 如果后台任務啟動的子作用域是請求作用域,那就是一個問題 - 當給定的HTTP請求完成時,將處理該請求作用域。 如果不是請求范圍,那很好。
  • 請求進入,MVC應用程序(或其他)中的控制器基於請求生命周期范圍生成。 你做了一些工作,並且基於控制器中的某些東西(可能是已解析的依賴關系),你把它交給那些把它交給最終在后台任務中結束的東西的東西。 如果您將后台任務交給由於請求范圍而存在的東西,那就太糟糕了。 如果它不是一個簡單的數據對象(沒有狀態,沒有IDisposable等),那么當請求結束時,你可能會從你的下方處理掉東西。

通常,較長時間運行的后台任務不應嘗試直接使用請求中的數據。 相反,你最好假裝后台任務正在監聽服務總線 - 創建一個沒有依賴關系的簡單數據傳輸對象(DTO)並將交給后台任務來執行操作。 這可以確保請求范圍不會與長期運行的任何內容聯系起來。

如果我正在調試這樣的事情,我會看到以下內容:

  • 后台任務或其任何依賴項是否已從請求生命周期范圍中解析? 檢查實際注冊。 如果你在任何地方都有InstancePerRequest ,那就不好了。 如果您有InstancePerLifetimeScope它可能會或可能不會很好 - InstancePerLifetimeScope可能意味着您從請求范圍中獲取了一個東西,而不是根容器。
  • “啟動任務的會話結束”時運行的操作是獲取來自請求范圍的一些信息? 是以某種方式解決了嗎? 從數據庫上下文或類似的東西? 遞交給MVC控制器(或其他)的數據庫上下文是否可以從與后台任務工作相關聯的數據對象下面關閉其連接?

您可能還對此Autofac.Analysis軟件包感興趣,該軟件包將Autofac事件記錄到Serilog。 我不能自己擔保,但它可以提供一些有用的見解。

我希望有所幫助。 如果沒有,至少它可以幫助你找出從哪里開始尋找。 同樣,我不認為理解范圍在內部表示Autofac將如何幫助您,但也許概念會。

服務應用程序池設置為按需,空閑超時為20分鍾 - 這就是為什么它看起來像是保持任務運行的用戶會話。 將服務應用程序池更改為始終運行並將空閑超時設置為0可解決問題。

暫無
暫無

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

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