【发布时间】:2015-06-07 23:10:22
【问题描述】:
有很多地方可以优雅地终止 C# 线程。但是,它们依赖于循环或在循环内执行的 if 条件,假设该语句将被频繁执行;因此,当设置stop bool 标志时,线程会快速退出。
如果我有一个不正确的线程怎么办?在我的例子中,这是一个设置为从服务器接收的线程,它经常阻塞从输入流中读取数据的调用,其中尚未提供任何数据,因此它会等待。
这是有问题的循环:
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);
}
}
块顶部的if 语句执行通常的停止线程优雅设置所做的工作:检查标志,如果设置了则终止线程。然而,这个线程通常会在下面几行之后找到,位于stream.Read。
鉴于此,有什么方法可以优雅地终止这个线程(即没有Aborting),并清理它的资源(有一个需要关闭的客户端)?
【问题讨论】:
-
减少您的流读取超时并更频繁地重试,让您有更多机会退出。
-
@Asad - 不知道这是可能的。我是用我拥有的
TcpClient还是底层的Socket TcpClient.Client来做这个? -
如果这是
TcpClient,您可以将其ReceiveTimeout属性设置为您喜欢的任何值。甚至可能还有一个构造函数可以让您在制作时设置它,尽管我不确定。 -
您的代码有一个重大缺陷,您假设您从
stream.Read收到一条完整的消息,您在单次阅读期间可能只收到 1/2 条消息。你真的应该有某种循环在那里检查'\0',如果你的消息没有空字符,它会在将data传递给ProcessMessage之前再次调用read。
标签: c# multithreading