簡體   English   中英

如何正確關閉服務

[英]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.

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