被Thread弄得快疯了,如何安全终止线程?

tqwboy 2009-08-08 09:19:13
先看看下面两段代码
  
//主程序

Thread createServer = null;
ServerThread listener = null;

//启动服务端监听线程
private void button1_Click(object sender, EventArgs e)
{
createServer = new Thread(new ThreadStart(WaitForConnect));
createServer.Start();
}

private void WaitForConnect()
{
listener = new ServerThread();
listener.StartListening();
}

//强制关闭窗口时,销毁线程,清理资源
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
listener.Dispose();
createServer.Abort();
}
catch
{ }
}



//服务端监听类

class ServerThread
{
int port = 9000; //监听端口号
IPAddress localAddr = IPAddress.Parse("127.0.0.1");

TcpListener listener = null;
Socket client = null;

public void StartListening()
{
listener = new TcpListener(localAddr,port);
listener.Start();

while (true)
{
try
{
MessageBox.Show("监听开始!");
client = listener.AcceptSocket();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}

public void Dispose()
{
try
{
if (client != null)
{
client.Close();
client = null;
}
listener.Stop();
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
}
}


这是我在做的一个多线程+Socket练习,程序主要有两部分组成,一个主窗口,一个服务端监听类。主窗口里有一个摁钮,当点击那个摁钮后,启动一个线程给服务端监听类,由服务端监听类进行客户端的连接监听。

在这个练习当中发现一个问题,当我点击窗口右上的关闭摁钮强制关闭程序后,发现程序并没有完全关闭,监听线程还驻留在系统里,打开进程管理器,看见程序的进程还在,于是就想在强制关闭窗口后,把线程给关闭了,于是就加上这句:createServer.Abort()

结果更大的问题来了。线程是成功关闭了,但是在关闭之前先弹出一个异常信息窗口,貌似在说要终止服务端监听类里的client = listener.AcceptSocket();这个语句,点击确定后线程才终止。这样就泄露了程序里的代码和工作,造成安全隐患。我试了一天也找不到解决办法,到底要怎么样才能安全的终止线程,请高手务必帮帮我啊,这个问题搞得我都吃不下饭了,今晚我就通宵等回答。
...全文
4057 39 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
天晓 2011-09-28
  • 打赏
  • 举报
回复
其实把线程的属性设置成这样的可以了。isbackground = true。
Element 2009-09-03
  • 打赏
  • 举报
回复
进来学习一下!
zhulinxiaofeng 2009-08-13
  • 打赏
  • 举报
回复
设置为后台进程只是主线程销毁会自动销毁这个线程,感觉是一种规避。
zll711 2009-08-11
  • 打赏
  • 举报
回复
你把线程设置为后台线程,isbackground = true ,看看
silent_hacker 2009-08-11
  • 打赏
  • 举报
回复
C#做socket? 学习下 呵呵~
hecker728 2009-08-11
  • 打赏
  • 举报
回复
经常使用暴力终止法。简单,方便。(进程的突然终止对结果没影响的话)
lybelmont 2009-08-11
  • 打赏
  • 举报
回复
使用 信号量是个 传统可靠的方法

建议你去看 《UNix网络编程》经典哦

里面讲了很多

你程序里的很多异常,不全是线程造成的

你的线程处理不正常,也造成了些网络错误产生的异常
slund 2009-08-11
  • 打赏
  • 举报
回复
学习。
注册失败 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 zhulinxiaofeng 的回复:]
建议使用信号量.
[/Quote]

终于看到有人说了线程里优雅的解决方案
四更山吐月 2009-08-11
  • 打赏
  • 举报
回复
使用信号量就行啦。
private static EventWaitHandle ewh_exception = new EventWaitHandle(false, EventResetMode.ManualReset);

while (true)
{
try
{
if(ewh_exception.waitOne(0,false))
{
ewh_exception.reset();
break;
}
if (listener.Pending())
{
MessageBox.Show("监听开始!");
client = listener.AcceptSocket();
}
else
Thread.Sleep(300);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}

}
如果你想结束,先ewh_exception。set();

跳出循环之后,你在把socket释放。
zhulinxiaofeng 2009-08-11
  • 打赏
  • 举报
回复
建议使用信号量.
天乐 2009-08-11
  • 打赏
  • 举报
回复
abort用于暴力终止线程,一般使用try语块来包着

形如:try {th.Abort();}catch(){}
tqwboy 2009-08-09
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 dancingbit 的回复:]
看来你不知道Pending()的真正作用,其实换句话说,就是未处理的连接请求的时候,这个方法返回true,否则返回false,这个时候,Accept方法永远不会挂起,即使它是一个阻塞方法。
[/Quote]

我改了一下我的代码:

if (listener.Pending())
{
MessageBox.Show("监听开始!");
client = listener.AcceptSocket();
}
else
{
MessageBox.Show("没有挂起!");
listening = false;
}


我试了一下,当我改成您这样的写法的时候,点击监听摁钮时,发现执行的是MessageBox.Show("没有挂起!")这一段。因为我没有写客户端来测试,所以我现在这样猜想:当执行了listener.Start()后,因为没有客户端连接近来,所以listener.Pending()为false;当有客户端连接进来的时候,listener.Pending()就为true,这时就执行client = listener.AcceptSocket()来接受客户端的连接请求。

不知道我理解对了吗?
dancingbit 2009-08-09
  • 打赏
  • 举报
回复
看来你不知道Pending()的真正作用,其实换句话说,就是未处理的连接请求的时候,这个方法返回true,否则返回false,这个时候,Accept方法永远不会挂起,即使它是一个阻塞方法。
zhushoudong 2009-08-09
  • 打赏
  • 举报
回复
可以用一个 bool的类型的变量去做个判断 然后执行listener.Dispose();
stszd604 2009-08-09
  • 打赏
  • 举报
回复
线程~~~~~~~~~~
tristan0429 2009-08-09
  • 打赏
  • 举报
回复
好在有循环,没循环就不能用变量标志来控制结束了。另外,如果循环线程里有阻塞方法的话用标志来控制也不太好,可能出现等很长时间的问题。 我就用 Abort(),再加个 Jion(时间),catch 里直接 return
psy0324 2009-08-09
  • 打赏
  • 举报
回复
线程这个啊...确实有些让人不明白..我以前做了判断一个循环所创建的线程是否完全结束,采用了变量标识...至于终止线程还不明白....
tqwboy 2009-08-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 dancingbit 的回复:]
当然,如果你不管它,自顾自去做其他的清理工作,它也会自行终止的。
[/Quote]

好的,非常感谢你的回答,让我学到不少东西。

过两天我就去结帖,留段时间让别人看一下,也让别人学习学习。有什么新问题我在另外开帖询问。

PS:第一次有专家那么热心回答我的问题,心里有点激动。
dancingbit 2009-08-09
  • 打赏
  • 举报
回复
当然,如果你不管它,自顾自去做其他的清理工作,它也会自行终止的。
加载更多回复(17)

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧