簡體   English   中英

如何在線程正在工作時停止服務(不使用Thread.Abort)

[英]How to stop a service when a thread is doing work (without using Thread.Abort)

我有一個服務在循環中運行一些不同的任務,直到服務停止。 但是,我調用Web服務和此調用的其中一個任務可能需要幾分鍾才能完成。 我希望能夠立即停止服務,“取消”Web服務調用而不調用Thread.Abort因為這會導致一些奇怪的行為,即使線程正在做的唯一事情是調用此Web服務方法。

如何取消或中斷同步方法調用(如果可能的話)? 或者我應該嘗試不同的方法?

我試圖使用AutoResetEvent ,然后調用Thread.Abort ,它在下面的代碼示例中運行正常,但是當在實際服務中實現此解決方案時,我得到一些意外的行為,可能是因為外部庫中發生了什么我是使用。

AutoResetEventThread.Abort

class Program
{
    static void Main(string[] args)
    {
        MainProgram p = new MainProgram();
        p.Start();
        var key = Console.ReadKey();
        if (key.Key == ConsoleKey.Q)
            p.Stop();
    }
}

class MainProgram
{
    private Thread workerThread;
    private Thread webServiceCallerThread;
    private volatile bool doWork;

    public void Start()
    {
        workerThread = new Thread(() => DoWork());
        doWork = true;
        workerThread.Start();
    }

    public void Stop()
    {
        doWork = false;
        webServiceCallerThread.Abort();
    }

    private void DoWork()
    {
        try
        {
            while (doWork)
            {
                AutoResetEvent are = new AutoResetEvent(false);
                WebServiceCaller caller = new WebServiceCaller(are);
                webServiceCallerThread = new Thread(() => caller.TimeConsumingMethod());
                webServiceCallerThread.Start();

                // Wait for the WebServiceCaller.TimeConsumingMethod to finish
                WaitHandle.WaitAll(new[] { are });

                // If doWork has been signalled to stop
                if (!doWork)
                    break;

                // All good - continue
                Console.WriteLine(caller.Result);
            }
        }
        catch (Exception e)
        {
            Console.Write(e);
        }
    }
}

class WebServiceCaller
{
    private AutoResetEvent ev;
    private int result;

    public int Result
    {
        get { return result; }
    }

    public WebServiceCaller(AutoResetEvent ev)
    {
        this.ev = ev;
    }

    public void TimeConsumingMethod()
    {
        try
        {
            // Simulates a method running for 1 minute
            Thread.Sleep(60000);
            result = 1;
            ev.Set();
        }
        catch (ThreadAbortException e)
        {
            ev.Set();
            result = -1;
            Console.WriteLine(e);
        }
    }
}

有人可以建議解決這個問題嗎?

試試這個

public void Start()
{
    workerThread = new Thread(() => DoWork());
    doWork = true;
    workerThread.IsBackground = true;
    workerThread.Start();
}

線程是后台線程或前台線程。 后台線程與前台線程相同,除了后台線程不會阻止進程終止。 一旦屬於進程的所有前台線程終止,公共語言運行庫就結束該進程。 任何剩余的后台線程都會停止並且不會完成。

有關更多詳細信息,請參閱http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx

解決方案非常簡單:除非您想要阻止幾分鍾,否則不要撥打幾分鍾的電話。 如果在沒有阻塞的情況下無法做任何特定事情,可能持續幾分鍾,就會大聲抱怨編寫強制要求的代碼(或者如果可能的話自己修復)。

一旦你打完電話,就太晚了。 你承諾了。 如果您調用的函數沒有提供中止它的安全方法,那么就沒有安全的方法了。

所有你想要做的就是一次做一個異步Web服務調用,並且在每個響應上進行另一個調用,你可以省去worker線程,只需進行異步調用,注冊回調並從回調中進行另一個異步調用:

class Program
{
    private static WebServiceCaller.TCMDelegate _wscDelegate;
    private static readonly WebServiceCaller _wsCaller = new WebServiceCaller();

    static void Main(string[] args)
    {
        _wscDelegate = _wsCaller.TimeConsumingMethod;

        MakeWSCallAsync();

        Console.WriteLine("Enter Q to quit");
        while (Console.ReadLine().ToUpper().Trim()!="Q"){}
    }

    public static void MakeWSCallAsync()
    {
        _wscDelegate.BeginInvoke(OnWSCallComplete, null);
    }

    public static void OnWSCallComplete(IAsyncResult ar)
    {
        Console.WriteLine("Result {0}", _wscDelegate.EndInvoke(ar));

        MakeWSCallAsync();
    }
}

class WebServiceCaller
{
    public delegate int TCMDelegate();

    public int TimeConsumingMethod()
    {
        try
        {
            // Simulates a method running for 1 minute
            Thread.Sleep(1000);
            return 1;
        }
        catch (ThreadAbortException e)
        {
            return -1;
        }
    }
}

沒有阻塞(好吧,控制台線程在ReadLine()上阻塞)並且沒有昂貴的 Windows內核模式同步對象(AutoResetEvent)。

暫無
暫無

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

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