2012-06-01 93 views
11

我需要執行一個無限循環並且想要在global.asax中啓動執行。 我的問題是我該怎麼做呢?我應該開始一個新的線程還是應該使用異步和任務或其他任何東西?在while循環中我需要做await TaskEx.Delay(5000);正確實現後臺進程ASP.NET中的線程

我該如何做到這一點,以便它不會阻塞任何其他進程,並且不會造成內存泄漏?

我使用VS10,AsyncCTP3,MVC4

編輯:

public void SignalRConnectionRecovery() 
     { 
      while (true) 
      { 
       Clients.SetConnectionTimeStamp(DateTime.UtcNow.ToString()); 
       await TaskEx.Delay(5000); 
      } 
     } 

所有我需要做的是作爲一個單獨的實例,只要全球的應用可以運行此。

編輯:解決

這是在Global.asax中最終的解決方案

protected void Application_Start() 
{ 
    Thread signalRConnectionRecovery = new Thread(SignalRConnectionRecovery); 
    signalRConnectionRecovery.IsBackground = true; 
    signalRConnectionRecovery.Start(); 

    Application["SignalRConnectionRecovery"] = signalRConnectionRecovery; 
} 


protected void Application_End() 
{ 
    try 
    { 
     Thread signalRConnectionRecovery = (Thread)Application["SignalRConnectionRecovery"]; 
     if (signalRConnectionRecovery != null && signalRConnectionRecovery.IsAlive) 
     { 
      signalRConnectionRecovery.Abort(); 
     } 
    } 
    catch 
    { 
      /// 
    } 
} 

我發現有關如何使用異步工人這個漂亮的文章:http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx

這: http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6

但我認爲我的需要s這一個將是完美的: http://forums.asp.net/t/1433665.aspx/1

+0

你到底想幹什麼? – jrummell

+1

Clients.SetConnectionTimeStamp做什麼?它的目的是什麼?你希望實現哪些特定的功能?如果你想要一個高質量的答案,你需要提供這些信息。 – cadrell0

+0

這是更好的做一個計時器。 – Aristos

回答

1

我發現這篇關於如何使用異步工作者的好文章,會試試看。 http://www.dotnetfunda.com/articles/article613-background-processes-in-asp-net-web-applications.aspx

而且這樣的: http://code.msdn.microsoft.com/CSASPNETBackgroundWorker-dda8d7b6

但我認爲我需要這將是一個完美的: http://forums.asp.net/t/1433665.aspx/1

+0

小心 - 無限循環會嚼碎你的處理器。此外,您必須確保您不會意外啓動這些事件的多個實例(這意味着一些多線程檢查)。 – JDB

+0

@ Cyborgx37嗯,這就是爲什麼我發佈了OP,但不幸的是在SO上有太多的噪音......另外,如果你自己讀了OP,你就會知道線程將會長時間的睡眠,所以在那裏那裏沒有CPU問題。 –

13

ASP.NET不是爲了處理這種需求而設計的。如果你需要不斷運行的東西,你最好創建一個windows服務。

更新

ASP.NET不適合長時間運行的任務。它旨在快速響應HTTP請求。出於幾個原因,請參閱Cyborgx37's answerCan I use threads to carry out long-running jobs on IIS?

立即更新

,你終於提到你與SignalR工作,我看你是想在ASP.NET主機SignalR,是否正確?我認爲你的方式是錯誤的,請參閱project wiki上引用的示例NuGet package。本示例使用IAsyncHttpHandler來管理任務。

+2

第一個鏈接沒有提供任何理由說明,爲什麼第二個鏈接僅表明服務器可能選擇在某個時間點回收應用程序池這一非常明顯的問題。 我還沒有聽到有效的擔憂,爲什麼這是一個「壞主意」。 要將某些東西排除在Windows服務中,使您的應用程序更難以部署,聽起來像是對我來說不好的主意。 有人有真正的理由還是僅僅是意識形態? – John

+0

_...非常明顯的擔心,服務器可能會選擇在某個點回收應用程序池。這是一個非常重要的事情... – jrummell

+0

所有應用程序在某個時刻停止運行,這不是ASP.NET獨有的。你是否反對在WinForms應用程序中做後臺作業,因爲用戶可以隨時點擊關閉按鈕?即使Windows服務器需要在服務器重新啓動時關閉。這有什麼不同? – John

8

你可以在你的global.asax中啓動一個線程,但它只會運行,直到你的asp.net進程被回收。這將至少每天發生一次,或者沒有人使用您的網站。如果流程得到回收,線程重啓的唯一方法就是在您的網站上點擊。所以線程不會繼續運行。

要獲得持續的過程,最好啓動一個Windows服務。

如果您執行'進程中'解決方案,它實際上取決於您正在做什麼。線程本身不會導致你在內存或死鎖問題。您應該添加meganism來停止應用程序停止時的線程。否則重新啓動需要很長時間,因爲它會等待你的線程停止。

+1

非常好!我沒有問題,他們得到回收。這是要求之一。 –

+0

謝謝!我用更多的細節編輯了我的問題。 –

+0

我同意同行。解決方案以及對此危險的警告可以在這篇偉大的文章中找到:http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in- asp-net.aspx/ –

2

這取決於您在while循環中想要完成的任務,但通常情況下,Windows Service是最好的答案。安裝Windows服務將要求您在Web服務器上擁有管理員權限。

隨着無限循環,最終會出現許多有關Windows消息泵的問題。即使應用程序沒有「執行」任何事情,這仍然可以讓Windows應用程序保持活躍狀態​​。沒有它,程序就會結束。

無限循環的問題在於,應用程序被卡住「執行」某些內容,從而阻止其他應用程序(或線程)「執行」他們的事情。已經有幾種解決方法,比如Windows Forms中的DoEvents,但它們在響應和資源管理方面都有一些嚴重的缺陷。 (可以在小型LOB應用程序上使用,也許不在Web服務器上)即使while循環位於單獨的線程上,它也會耗盡所有可用的處理能力。

Asynchronus編程實際上是針對長時間運行的流程而設計的,例如等待數據庫返回結果或等待打印機聯機。在這些情況下,這是需要很長時間而不是一個循環的外部過程。

如果窗口服務不可行,那麼我認爲你最好的選擇是用自己的消息泵建立一個單獨的線程,但它有點複雜。我從來沒有在Web服務器上完成它,但你可能能夠啓動一個應用程序。這將爲您提供消息泵並允許您響應Windows事件等。唯一的問題是,這將啓動Windows應用程序(WPFWinForms),這在Web服務器上可能不合需要。

你想完成什麼?你還有另外一種方法可以解決這個問題嗎?

+0

謝謝!我用更多的細節編輯了我的問題。 –