有很多地方可以优雅地终止 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);
}
}
The if
块顶部的语句执行通常的正常停止线程设置的操作:检查标志,如果设置了则终止线程。然而,通常会发现该线程在下面几行等待,即stream.Read
.
鉴于此,是否有任何方法可以优雅地终止该线程(即没有Abort
ing),并清理其资源(有一个客户端需要关闭)?
假设您可以使用异步/任务,则干净停止异步和 IO 操作的方法是使用CancelationToken
连接到一个CancelationTokenSource
。下面的代码片段展示了其应用于简化版本代码时的用法的简化示例。
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();
}
}
}
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)