2013-07-10 156 views
11

這是我的問題:我需要在ApiController中調用多個第三方方法。這些方法的簽名是Task DoSomethingAsync(SomeClass someData, SomeOtherClass moreData)。我希望這些調用在ApiController將數據發送回客戶端後在後臺繼續運行。當DoSomethingAsync完成時,我想做一些日誌記錄,也許將一些數據保存到文件系統。我怎樣才能做到這一點?我寧願使用asyny/await語法。WebAPI中的長時間運行任務

+0

你的任務有類似'.ContinueWith'。這是你可以做記錄的地方。 –

+0

當你說「在ApiController將數據發送回客戶端之後」時,你的意思是說該連接也關閉了嗎?客戶端是否可以在保持連接打開的同時從服務器接收數據? –

+0

是的,連接已關閉。 – TEst16

回答

7

Stephen介紹了爲什麼要在ApiController中啓動基本上長時間運行的「即燃即用」任務是一個壞主意。

也許你應該創建一個單獨的服務來執行那些「即丟即忘」的任務。 服務可能是一個不同的ApiController,隊列後面的工作者,任何可以獨立託管並具有獨立生命週期的東西。

這將使不同任務生命週期的管理變得更容易,並將長時間運行的任務與ApiController的核心職責分開。

+1

爲什麼最好有一個單獨的服務的另一個原因是使其更容易擴展。例如,也許你發現你需要更多的服務器來運行長時間運行的任務,但沒有更多的服務器來運行你的網站。通過在開始時分解這些,您可以更好地定製您的擴展解決方案。 – jt000

16

你幾乎從不想這樣做。這幾乎總是一個很大的錯誤。

ASP.NET(以及大多數其他服務器)的工作原理是,一旦完成所有請求,就可以安全地拆除您的服務。所以你有沒有保證你的日誌將被完成,或者你的數據將被寫入磁盤。特別是對於磁盤寫入,寫入操作完全可能會損壞。

這就是說,如果你是絕對相信,要實現這個極其危險設計,您可以使用BackgroundTaskManager from my blog

+1

在Azure-WebJobs之前更正。現在你可以用Azure-WebJobs來做到這一點。工人角色是最穩健的方法。 – RickAndMSFT

+0

我發現這是一個可以接受的交易,例如:調試日誌記錄,性能記錄,事件跟蹤(使用外部服務)。在所有這些情況下,「即丟即用」的語義是可以接受的,我們並不在乎在服務拆除的情況下單個事件是否會丟失。還是有我失蹤的東西? –

+0

@JohannesRudolph:我想說的主要用例是緩存更新。如果您接受日誌可能不包含所有數據,那麼這是一種可接受的日誌記錄方式。我會將「事件跟蹤」解釋爲業務需求,因此不是一個很好的用例。如果「事件跟蹤」不重要,那麼「調試日誌記錄」,「性能記錄」和「事件跟蹤」只是三種不同的日誌記錄。請注意,ASP.NET 4.5.2現在具有類似的內置內容。 –

16

好消息,有在.NET 4.5.2叫QueueBackgroundWorkItem一個新的解決方案API。它的使用非常簡單:

HostingEnvironment.QueueBackgroundWorkItem(ct => DoSomething(a, b, c)); 

這裏有一篇文章詳細描述它。

https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/

而這裏的anohter一篇文章,提到在這個線程未提及的其他一些方法。 http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

+3

如果長時間運行的任務不是真正的長時間運行,也就是說它可以在不到90秒的時間內完成,QueueBackgroundWorkItem可以是一個解決方案。如果真的需要長時間運行,則需要另一種解決方案(如將它交給Windows服務) –

+0

我無法在Windows服務(後端數據層)內的自託管WebAPI中使用此工具。 –