c# 在timer里不能控制其他线程终止吗?

抚落霞 2015-08-17 03:42:58
我在线程内创建一个timer来控制线程本身,但是发现在timer里不能控制线程终止。谢了个小测试:
class Program
{
static void Main(string[] args)
{
Test t = new Test();
Console.ReadLine();
}
}
class Test
{
public Thread a;
public Test()
{
a = new Thread(new ThreadStart(test));
a.Start();
}
int i = 0;
private void test()
{

System.Timers.Timer ab = new System.Timers.Timer();
ab.Interval = 1000;
ab.Elapsed += delegate
{
if (i > 5)
{
if (a.IsAlive) { a.Abort(); Console.WriteLine("线程已执行停止!"); }
if (a.IsAlive) { Console.WriteLine("线程仍未停止!"); }
}
ab.Stop();
ab.Dispose();
};
ab.Start();
while (true)
{
i++;
Console.WriteLine(i.ToString());
}
}
}
...全文
484 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
KK3K2005 2015-08-18
  • 打赏
  • 举报
回复
while里面要加sleep
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
算了,凡是还是靠自己。弄清楚了,如果线程,线程还在处于等待返回阶段,使用abort,线程进入AbortRequested状态,所以线程不会停止。而我通信的时候有一句netwetstream.read函数,这句函数如果在网络通信中没有数据,则一直处于等待返回状态,导致线程无法通过abort完全终止。解决方法就是设置netwetstream的readtimeout,让read函数停止返回状态。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
我找到原因了,是因为abort()终止时,线程还在处于等待返回阶段,使用abort,线程进入AbortRequested状态。那请问各位,在开发的时候,tcpClient客户端接收数据线程是怎么终止的,加入信号量的?如果connect,但是没有数据的话,好像线程无法终止。例如如下小例子,在线程函数内加入alive信号量,但是如果没有收到数据的话,即使alive=false,程序还是会死 bufLen = clientTcp.Available; 这句在线程里。

 private void ConnectToServer()
        {
            byte[] data = new byte[1024];
            IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("192.168.31.144"), 8888);
            //clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientTcp = new TcpClient();
            try
            {
                clientTcp.Connect(ipep);
            }
            catch (SocketException ex)
            {
                MessageBox.Show("connect error: " + ex.Message);
                return;
            }

            ns = clientTcp.GetStream();
            while (alive)     //信号量
            {
             
                int bufLen = 0;
                try
                {
                    bufLen = clientTcp.Available;    //这里会一直停在这里
                    ns.Read(data, 0, bufLen);
                    if (bufLen == 0)
                    {
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Receive Error:" + ex.Message);
                    return;
                }

                string clientcommand = System.Text.Encoding.ASCII.GetString(data).Substring(0, bufLen);

                lstClient.Items.Add(clientcommand);

            }
        }
_lee_chong 2015-08-17
  • 打赏
  • 举报
回复
引用 25 楼 m85647669 的回复:
[quote=引用 23 楼 lc316546079 的回复:] 我想说的是,这讨论没意义呢。。。。如果你要停止子线程,最好的方式肯定不是abort这个已过时的方法诶, 就算它能停止线程也强烈不建议那么做,你根本没法控制在abort的时候线程到底在干什么,太不安全了; ----- 用这种方式吧,更和谐

        bool _stopThread = false;        // 是否要结束线程的标识
        bool _threadOver = false;   // 线程是否已经结束的标识
        private void test()
        {
            _threadOver = false;
            _stopThread = false;
            System.Timers.Timer ab = new System.Timers.Timer();
            ab.Interval = 1000;
            ab.Elapsed += delegate
            {
                if (i > 5)
                {
                    if (_threadOver) { _stopThread=true; Console.WriteLine("线程已执行停止!"); }
                    if (_threadOver) { Console.WriteLine("线程仍未停止!"); }
                    ab.Stop();
                    ab.Dispose();
                }               
            };
            ab.Start();
            while (true)
            {
                if(_stopThread) break;
                i++;
                Console.WriteLine(i.ToString());
                Thread.Sleep(1000);
            }
            _threadOver = true;
        }
这是小测试,不是我的主程序代码。很短的小线程函数用信号量好控制,我这是大的有远程通信交互的线程,所以采用计时器计算超时。而且是多线程的,用信号量很难做到多个线程匹配。[/quote] ----------------------------- 真心非常不建议用abort,调用他的结果是未知,不是什么情况下都能结束线程诶; 另外,我这不也只是个简单的例子么,我所有的多线程操作,只要涉及需要控制结束的全是这样,包括以前一次写web接口(一个web接口开启工作线程,一个web接口停止并获得工作结果); 。。。具体怎么用,”思考”, “设计“,可行性是一定有的,就看你怎么考虑了
加油馒头 2015-08-17
  • 打赏
  • 举报
回复
引用 25 楼 m85647669 的回复:
[quote=引用 23 楼 lc316546079 的回复:] 我想说的是,这讨论没意义呢。。。。如果你要停止子线程,最好的方式肯定不是abort这个已过时的方法诶, 就算它能停止线程也强烈不建议那么做,你根本没法控制在abort的时候线程到底在干什么,太不安全了; ----- 用这种方式吧,更和谐

        bool _stopThread = false;        // 是否要结束线程的标识
        bool _threadOver = false;   // 线程是否已经结束的标识
        private void test()
        {
            _threadOver = false;
            _stopThread = false;
            System.Timers.Timer ab = new System.Timers.Timer();
            ab.Interval = 1000;
            ab.Elapsed += delegate
            {
                if (i > 5)
                {
                    if (_threadOver) { _stopThread=true; Console.WriteLine("线程已执行停止!"); }
                    if (_threadOver) { Console.WriteLine("线程仍未停止!"); }
                    ab.Stop();
                    ab.Dispose();
                }               
            };
            ab.Start();
            while (true)
            {
                if(_stopThread) break;
                i++;
                Console.WriteLine(i.ToString());
                Thread.Sleep(1000);
            }
            _threadOver = true;
        }
这是小测试,不是我的主程序代码。很短的小线程函数用信号量好控制,我这是大的有远程通信交互的线程,所以采用计时器计算超时。而且是多线程的,用信号量很难做到多个线程匹配。[/quote] 可以考虑用变量控制线程
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 23 楼 lc316546079 的回复:
我想说的是,这讨论没意义呢。。。。如果你要停止子线程,最好的方式肯定不是abort这个已过时的方法诶, 就算它能停止线程也强烈不建议那么做,你根本没法控制在abort的时候线程到底在干什么,太不安全了; ----- 用这种方式吧,更和谐

        bool _stopThread = false;        // 是否要结束线程的标识
        bool _threadOver = false;   // 线程是否已经结束的标识
        private void test()
        {
            _threadOver = false;
            _stopThread = false;
            System.Timers.Timer ab = new System.Timers.Timer();
            ab.Interval = 1000;
            ab.Elapsed += delegate
            {
                if (i > 5)
                {
                    if (_threadOver) { _stopThread=true; Console.WriteLine("线程已执行停止!"); }
                    if (_threadOver) { Console.WriteLine("线程仍未停止!"); }
                    ab.Stop();
                    ab.Dispose();
                }               
            };
            ab.Start();
            while (true)
            {
                if(_stopThread) break;
                i++;
                Console.WriteLine(i.ToString());
                Thread.Sleep(1000);
            }
            _threadOver = true;
        }
这是小测试,不是我的主程序代码。很短的小线程函数用信号量好控制,我这是大的有远程通信交互的线程,所以采用计时器计算超时。而且是多线程的,用信号量很难做到多个线程匹配。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 22 楼 dongxinxi 的回复:
程序中尽量不要用Thread.Abort()去终止线程 timer线程,跟它执行任务的(工作线程)并不是同一个线程,工作线程是ThreadPool中的 while(true)不应该timer写在一起,应该放在工作线程中
我这个还真不好用信号量控制,因为线程内有多个与远程机器进行数据收发,用信号量不能立即停止线程。而且多线程,信号量也不好控制匹配,万不得已才用的about();
_lee_chong 2015-08-17
  • 打赏
  • 举报
回复
我想说的是,这讨论没意义呢。。。。如果你要停止子线程,最好的方式肯定不是abort这个已过时的方法诶, 就算它能停止线程也强烈不建议那么做,你根本没法控制在abort的时候线程到底在干什么,太不安全了; ----- 用这种方式吧,更和谐

        bool _stopThread = false;        // 是否要结束线程的标识
        bool _threadOver = false;   // 线程是否已经结束的标识
        private void test()
        {
            _threadOver = false;
            _stopThread = false;
            System.Timers.Timer ab = new System.Timers.Timer();
            ab.Interval = 1000;
            ab.Elapsed += delegate
            {
                if (i > 5)
                {
                    if (_threadOver) { _stopThread=true; Console.WriteLine("线程已执行停止!"); }
                    if (_threadOver) { Console.WriteLine("线程仍未停止!"); }
                    ab.Stop();
                    ab.Dispose();
                }               
            };
            ab.Start();
            while (true)
            {
                if(_stopThread) break;
                i++;
                Console.WriteLine(i.ToString());
                Thread.Sleep(1000);
            }
            _threadOver = true;
        }
  • 打赏
  • 举报
回复
程序中尽量不要用Thread.Abort()去终止线程 timer线程,跟它执行任务的(工作线程)并不是同一个线程,工作线程是ThreadPool中的 while(true)不应该timer写在一起,应该放在工作线程中
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 15 楼 m85647669 的回复:
[quote=引用 8 楼 wc_ling 的回复:]

  public Thread a = new Thread(test);
 a.Start();
   static void test()
        {
            while (true)
            {
                i++;
                Console.WriteLine(i.ToString());
            }
        }
private void timer1_Tick(object sender, EventArgs e)
        {
            if (i > 5)
            {
                if (a.IsAlive) { a.Abort(); MessageBox.Show("线程已执行停止!"); }
                if (a.IsAlive) { MessageBox.Show("线程仍未停止!"); }
            }
            timer1.Enabled = false; 
        }
这样写就可以了
不是的,我这边只是个小测试。不过在我的另一个正在开发的程序里,线程内创建的Timer 无法about线程列表里的某个线程[/quote] Control.CheckForIllegalCrossThreadCalls = false; byte[] by; int time = 0; System.Timers.Timer Ask_Send = new System.Timers.Timer(); Ask_Send.Interval = 1000 * int.Parse(Update_Info.Response_interval); //发送请求 Ask_Send.Elapsed += delegate { by = Method_fun.hexStringToByte(b.getUpdateAsk()); listBox1.Items.Add(msgprint(ip.Address.ToString(), "Send: " + b.getUpdateAsk())); listBox1.SelectedIndex = listBox1.Items.Count - 1; if (client_list[i].mySw != null && Log.IsLogStart) { try { client_list[i].mySw.WriteLine(msgprint2(ip.Address.ToString(), "Send: " + b.getUpdateAsk())); client_list[i].mySw.Flush(); } catch (Exception exab) { } } try { net.Write(by, 0, by.Length); } catch (SocketException ex) { listBox1.Items.Add(msgprint(ip.Address.ToString(), "connect error: " + ex.Message)); listBox1.SelectedIndex = listBox1.Items.Count - 1; if (client_list[i].mySw != null && Log.IsLogStart) { try { client_list[i].mySw.WriteLine(msgprint2(ip.Address.ToString(), "connect error: " + ex.Message)); client_list[i].mySw.Flush(); } catch (Exception exab) { } } if (client_list[i].mySw != null && client_list[i].myFs != null) { client_list[i].mySw.Flush(); client_list[i].mySw.Close(); client_list[i].myFs.Close(); } client_list[i].clientThread.Abort(); Ask_Send.Stop(); Ask_Send.Dispose(); } time++; for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } this.dataGridView1.Rows[i].Cells[5].Value = "已发送第" + time.ToString() + "次升级请求"; if (time >= 3) { //设置相关请求失败界面内容 for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } this.dataGridView1.Rows[i].Cells[3].Value = global::Update.Properties.Resources.failure; this.dataGridView1.Rows[i].Cells[4].Value = 0; this.dataGridView1.Rows[i].Cells[5].Value = "升级请求回应超时,升级失败!"; client_list[i].client_cancelThread.Start(client_list[i]); if (client_list[i].mySw != null && client_list[i].myFs != null) { client_list[i].mySw.Flush(); client_list[i].mySw.Close(); client_list[i].myFs.Close(); } for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } //此处为线程是否关闭测试段 if (client_list[i].clientThread.IsAlive) { Ask_Send.Stop(); Ask_Send.Dispose(); client_list[i].clientThread.Abort(); listBox1.Items.Add(i.ToString() + "停止了!"); } if (client_list[i].clientThread.IsAlive) listBox1.Items.Add(i.ToString() + "还在!"); } }; Ask_Send.Start(); 测试地点出现这个问题。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 17 楼 clark_kidd 的回复:
因为 a.Abort(); 执行完后 在很短的时间内, while (true) 里的代码还在执行,所以 a.IsAlive 这在这个很短的时间段内仍 == true;
好像不是这个问题。帮我看下下面的,我的程序代码。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 15 楼 m85647669 的回复:
[quote=引用 8 楼 wc_ling 的回复:]

  public Thread a = new Thread(test);
 a.Start();
   static void test()
        {
            while (true)
            {
                i++;
                Console.WriteLine(i.ToString());
            }
        }
private void timer1_Tick(object sender, EventArgs e)
        {
            if (i > 5)
            {
                if (a.IsAlive) { a.Abort(); MessageBox.Show("线程已执行停止!"); }
                if (a.IsAlive) { MessageBox.Show("线程仍未停止!"); }
            }
            timer1.Enabled = false; 
        }
这样写就可以了
不是的,我这边只是个小测试。不过在我的另一个正在开发的程序里,线程内创建的Timer 无法about线程列表里的某个线程[/quote] Control.CheckForIllegalCrossThreadCalls = false; byte[] by; int time = 0; System.Timers.Timer Ask_Send = new System.Timers.Timer(); Ask_Send.Interval = 1000 * int.Parse(Update_Info.Response_interval); //发送请求 Ask_Send.Elapsed += delegate { by = Method_fun.hexStringToByte(b.getUpdateAsk()); listBox1.Items.Add(msgprint(ip.Address.ToString(), "Send: " + b.getUpdateAsk())); listBox1.SelectedIndex = listBox1.Items.Count - 1; if (client_list[i].mySw != null && Log.IsLogStart) { try { client_list[i].mySw.WriteLine(msgprint2(ip.Address.ToString(), "Send: " + b.getUpdateAsk())); client_list[i].mySw.Flush(); } catch (Exception exab) { } } try { net.Write(by, 0, by.Length); } catch (SocketException ex) { listBox1.Items.Add(msgprint(ip.Address.ToString(), "connect error: " + ex.Message)); listBox1.SelectedIndex = listBox1.Items.Count - 1; if (client_list[i].mySw != null && Log.IsLogStart) { try { client_list[i].mySw.WriteLine(msgprint2(ip.Address.ToString(), "connect error: " + ex.Message)); client_list[i].mySw.Flush(); } catch (Exception exab) { } } if (client_list[i].mySw != null && client_list[i].myFs != null) { client_list[i].mySw.Flush(); client_list[i].mySw.Close(); client_list[i].myFs.Close(); } client_list[i].clientThread.Abort(); Ask_Send.Stop(); Ask_Send.Dispose(); } time++; for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } this.dataGridView1.Rows[i].Cells[5].Value = "已发送第" + time.ToString() + "次升级请求"; if (time >= 3) { //设置相关请求失败界面内容 for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } this.dataGridView1.Rows[i].Cells[3].Value = global::Update.Properties.Resources.failure; this.dataGridView1.Rows[i].Cells[4].Value = 0; this.dataGridView1.Rows[i].Cells[5].Value = "升级请求回应超时,升级失败!"; client_list[i].client_cancelThread.Start(client_list[i]); if (client_list[i].mySw != null && client_list[i].myFs != null) { client_list[i].mySw.Flush(); client_list[i].mySw.Close(); client_list[i].myFs.Close(); } for (i = 0; i < client_list.Count; i++) { if (client_list[i].ip.Address.Equals(ip.Address)) break; } //此处为线程是否关闭测试段 if (client_list[i].clientThread.IsAlive) { Ask_Send.Stop(); Ask_Send.Dispose(); client_list[i].clientThread.Abort(); listBox1.Items.Add(i.ToString() + "停止了!"); } if (client_list[i].clientThread.IsAlive) listBox1.Items.Add(i.ToString() + "还在!"); } }; Ask_Send.Start(); 测试地点出现这个问题。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 8 楼 wc_ling 的回复:

  public Thread a = new Thread(test);
 a.Start();
   static void test()
        {
            while (true)
            {
                i++;
                Console.WriteLine(i.ToString());
            }
        }
private void timer1_Tick(object sender, EventArgs e)
        {
            if (i > 5)
            {
                if (a.IsAlive) { a.Abort(); MessageBox.Show("线程已执行停止!"); }
                if (a.IsAlive) { MessageBox.Show("线程仍未停止!"); }
            }
            timer1.Enabled = false; 
        }
这样写就可以了
不是的,我这边只是个小测试。不过在我的另一个正在开发的程序里,线程内创建的Timer 无法about线程列表里的某个线程
Poopaye 2015-08-17
  • 打赏
  • 举报
回复
引用 16 楼 m85647669 的回复:
所以不是变量i的问题
所以程序也没问题啊
clark_kidd 2015-08-17
  • 打赏
  • 举报
回复
因为 a.Abort(); 执行完后 在很短的时间内, while (true) 里的代码还在执行,所以 a.IsAlive 这在这个很短的时间段内仍 == true;
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 13 楼 shingoscar 的回复:
我的停止了啊
所以不是变量i的问题
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 10 楼 shingoscar 的回复:
[quote=引用 6 楼 m85647669 的回复:] [quote=引用 4 楼 shingoscar 的回复:] if (i > 5) 这个判断里,i永远等于0,进不去
程序线程里有个 i++[/quote] 请再仔细想想,你程序里的i++和判断里的i是同一个变量吗?[/quote] 难道不是一个变量吗?跑跑看吧。
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 8 楼 wc_ling 的回复:

  public Thread a = new Thread(test);
 a.Start();
   static void test()
        {
            while (true)
            {
                i++;
                Console.WriteLine(i.ToString());
            }
        }
private void timer1_Tick(object sender, EventArgs e)
        {
            if (i > 5)
            {
                if (a.IsAlive) { a.Abort(); MessageBox.Show("线程已执行停止!"); }
                if (a.IsAlive) { MessageBox.Show("线程仍未停止!"); }
            }
            timer1.Enabled = false; 
        }
这样写就可以了
不是的,我这边只是个小测试。不过在我的另一个正在开发的程序里,线程内创建的Timer 无法about线程列表里的某个线程
Poopaye 2015-08-17
  • 打赏
  • 举报
回复

我的停止了啊
抚落霞 2015-08-17
  • 打赏
  • 举报
回复
引用 10 楼 shingoscar 的回复:
[quote=引用 6 楼 m85647669 的回复:] [quote=引用 4 楼 shingoscar 的回复:] if (i > 5) 这个判断里,i永远等于0,进不去
程序线程里有个 i++[/quote] 请再仔细想想,你程序里的i++和判断里的i是同一个变量吗?[/quote] 难道不是一个变量吗?跑跑看吧。
加载更多回复(10)

110,532

社区成员

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

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

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