[英]How to shutdown a service correctly
我有一個服務,它始終從隊列中讀取,我希望服務能夠處理在應用程序關閉之前收到的最新項目。 我在1-2個月前做過一些研究並找到了一種方法,但它沒有用。 我的意思是不工作,當服務停止時,它需要99%的CPU,永遠不會退出。 所以我試圖鎖定導入函數並鎖定close函數,將import設置為false然后繼續。 同樣的事情發生在這里,所以我在導入函數中添加了一個變量,然后在變量為true時進行循環。 不用說它不起作用。
public void StopImportSms()
{
EventLogger.Write("Waiting for lock to false", EventLogEntryType.Information);
_import = false;
while (_lock)
{
}
EventLogger.Write("Import is disabled", EventLogEntryType.Information);
}
。
private void ImportSms()
{
while (_import)
{
_lock = true;
var messages = ReadMessages(consumer);
if (!messages.Any())
{
_lock = false;
continue;
}
//Db insert messages
//Send ack to queue
_lock = false;
Thread.Sleep(5);
}
。
public void StartImportSms()
{
Task.Factory.StartNew(ImportSms);
}
這是使用事件而不是標志最好解決的問題,因為可以在不使用CPU時間的情況下等待事件(就像當前的while
循環那樣)。
我假設第二個代碼片段在一個單獨的線程中運行,你沒有顯示它,所以我將通過_importThread
表示該線程(這個Thread
對象需要可以從StopImportSms()
方法訪問)。 您還需要聲明一個ManualResetEvent
字段:
ManualResetEvent _stopEvent = new ManualResetEvent(false);
然后你的導入循環變為:
while (!_stopEvent.WaitOne(0))
{
var messages = ReadMessages(consumer);
// ... further processing here?
}
StopImportSms()
更改為:
public void StopImportSms()
{
EventLogger.Write("Waiting for import to stop...", EventLogEntryType.Information);
// Instruct the import thread to stop
_stopEvent.Set();
// Wait for the thread to complete
_importThread.Join();
EventLogger.Write("Import is disabled", EventLogEntryType.Information);
}
編輯:
由於您正在為導入方法使用任務,因此您可能需要嘗試以下方法:
在類中聲明CancellationTokenSource
字段:
CancellationTokenSource _tokenSource = new CancellationTokenSource();
創建導入任務時,請使用以下內容(您需要在實現消息導入循環的方法中添加CancellationToken
參數):
var token = _tokenSource.Token;
_importTask = Task.Factory.StartNew(() => ImportMethod(/* other parameters? */ token), token);
然后,實現導入任務的方法更改為:
private void ImportMethod(/* other parameters? */ CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var messages = ReadMessages(consumer);
// ... further processing here?
}
}
最后,您的StopImportSms()
方法變為:
public void StopImportSms()
{
EventLogger.Write("Waiting for import to stop...", EventLogEntryType.Information);
// Instruct the import task to stop
_tokenSource.Cancel();
// Wait for the import task to complete
_importTask.Wait(/* optionally, add a timeout in milliseconds here */);
EventLogger.Write("Import is disabled", EventLogEntryType.Information);
}
值得注意的是,由於這不使用CancellationToken.ThrowIfCancellationRequested()
方法,任務將指示它運行完成(即_importTask.Wait()
返回后, _importTask.Status
將是TaskStatus.RanToCompletion
,而不是比TaskStatus.Canceled
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.