我怎样才能优雅地终止阻塞的线程? [英] How can I gracefully terminate a BLOCKED thread?

查看:119
本文介绍了我怎样才能优雅地终止阻塞的线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有很多与优雅终止C#线程处理的地方。但是,他们依靠一个循环或者条件的循环,它假定该语句将被频繁地执行内部执行;因此,当停止布尔标志设置,线程退出快。

There are plenty of places that deal with terminating C# threads gracefully. However, they rely on a loop or if condition executing inside a loop, which assumes that this statement will be executed frequently; thus, when the stop bool flag is set, the thread exits quickly.

如果我有一个线程此是不是真的?于我而言,这是设置为从服务器,它在通话读取输入流,其中还没有提供这样它等待数据频繁块。

What if I have a thread in which this is not true? In my case, this is a thread set up to receive from a server, which frequently blocks on a call to read data from the input stream, where none is yet provided so it waits.

下面是有问题的循环中的线程:

Here is the thread in question's loop:

    while (true)
        {
            if (EndThread || Commands.EndRcvThread)
            {
                Console.WriteLine("Ending thread.");
                return;
            }

            data = "";
            received = new byte[4096];

            int bytesRead = 0;
            try
            {
                bytesRead = stream.Read(received, 0, 4096);
            }
            catch (Exception e)
            {
                Output.Message(ConsoleColor.DarkRed, "Could not get a response from the server.");
                if (e.GetType() == Type.GetType("System.IO.IOException"))
                {
                    Output.Message(ConsoleColor.DarkRed, "It is likely that the server has shut down.");
                }
            }

            if (bytesRead == 0)
            {
                break;
            }

            int endIndex = received.Length - 1;
            while (endIndex >= 0 && received[endIndex] == 0)
            {
                endIndex--;
            }

            byte[] finalMessage = new byte[endIndex + 1];
            Array.Copy(received, 0, finalMessage, 0, endIndex + 1);

            data = Encoding.ASCII.GetString(finalMessage);

            try
            {
                ProcessMessage(data);
            }
            catch (Exception e)
            {
                Output.Message(ConsoleColor.DarkRed, "Could not process the server's response (" + data + "): " + e.Message);
            }
        }



如果语句在块的顶部确实平时停止,一个线程优雅设置做什么:检查一个标志,如果它被设置终止线程。然而,这个线程通常被发现等待几行进一步下跌,在 stream.Read

The if statement at the top of the block does what the usual stopping-a-thread-gracefully setup does: checks a flag, terminates the thread if it's set. However, this thread is usually to be found waiting a few lines further down, at stream.Read.

由于这一点,有没有什么办法可以正常终止该线程(即无中止 ING),并清理其资源(有这个需要关闭客户端)?

Given this, is there any way to gracefully terminate this thread (i.e. no Aborting), and clean up its resources (there's a client that needs to be closed)?

推荐答案

假设你可以使用异步/任务,做异步和IO操作的清洁停止的方式是用 CancelationToken 连接到一个 CancelationTokenSource 。下面的代码片段说明当适用于您的代码的简化版本,其使用的一个简单的例子。

Assuming you can use async / Tasks, the way to do clean stopping of async and IO operations is with a CancelationToken that is connected to a CancelationTokenSource. The below code snippet illustrates a simplified example of its usage when applied to a simplified version of your code.

class MyNetworkThingy 
{
    public async Task ReceiveAndProcessStuffUntilCancelled(Stream stream, CancellationToken token)
    {
        var received = new byte[4096];
        while (!token.IsCancellationRequested)
        {
            try
            {
                var bytesRead = await stream.ReadAsync(received, 0, 4096, token);
                if (bytesRead == 0 || !DoMessageProcessing(received, bytesRead))
                    break; // done.
            }
            catch (OperationCanceledException)
            {
                break; // operation was canceled.
            }
            catch (Exception e)
            {
                // report error & decide if you want to give up or retry.
            }
        }
    }

    private bool DoMessageProcessing(byte[] buffer, int nBytes)
    {
        try
        {
            // Your processing code.
            // You could also make this async in case it does any I/O.
            return true;
        }
        catch (Exception e)
        {
            // report error, and decide what to do.
            // return false if the task should not
            // continue.
            return false;
        }
    }
}

class Program
{
    public static void Main(params string[] args)
    {
        using (var cancelSource = new CancellationTokenSource())
        using (var myStream = /* create the stream */)
        {
            var receive = new MyNetworkThingy().ReceiveAndProcessStuffUntilCancelled(myStream, cancelSource.Token);
            Console.WriteLine("Press <ENTER> to stop");
            Console.ReadLine();
            cancelSource.Cancel();
            receive.Wait();
        }
    }
}



.

这篇关于我怎样才能优雅地终止阻塞的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆