Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 立即终止无环线程而不中止或挂起_C#_Multithreading_Tcpclient_Terminate_Suspend - Fatal编程技术网

C# 立即终止无环线程而不中止或挂起

C# 立即终止无环线程而不中止或挂起,c#,multithreading,tcpclient,terminate,suspend,C#,Multithreading,Tcpclient,Terminate,Suspend,我正在实现一个协议库。这里有一个简单的描述 main函数内的主线程将始终检查networkstream(在tcpclient内)上是否有某些数据可用。假设response是接收到的消息,thread是一个正在运行的线程 thread = new Thread(new ThreadStart(function)); thread.IsBackground = true; thread.Start(); while(true){ response = receiveMessage(); if

我正在实现一个协议库。这里有一个简单的描述

main函数内的主线程将始终检查networkstream(在tcpclient内)上是否有某些数据可用。假设response是接收到的消息,thread是一个正在运行的线程

thread = new Thread(new ThreadStart(function));
thread.IsBackground = true;
thread.Start();

while(true){

response = receiveMessage();

if (response != null)
     {                
      thread.Suspend();
      //I am searching for an alternative for the line above and not thread.Abort().

      thread2 = new Thread(new ThreadStart(function2));
      thread2.IsBackground = true;
      thread2.Start();         
     }
}
到目前为止还不错,实际上while循环中有更多的消息,还有一个状态机用于处理不同种类的传入消息,但这应该足够了。 (也不仅仅是功能“function”和“function2”)

因此,无论如何,在这个应用程序中,函数的内部外观并不清楚,因为协议对程序员是隐藏的,并且是一个库。这意味着协议将启动一些程序员定义的函数作为线程,具体取决于程序在协议中的状态

因此,如果收到特殊响应(例如callAnotherFunction消息),我想终止 一个线程(这里称为“线程”)突然出现,比如说在100毫秒内。但我不知道它是否在循环内执行,以及在终止之前需要多少处理

如何在没有不推荐的Suspend或ExceptionRowing Abort函数的情况下停止这些线程? (请注意,我无法强制函数的程序员捕获ThreadAbortException。)

还是我需要一个不同的程序架构?
(顺便说一句,我已经决定在receiveMessage中设置循环,以便在主函数中轮询网络流,因为任何时候都可能出现消息)。

挂起真的很邪恶,特别是在您试图使用它的方式中——永远停止线程执行。它将保留线程拥有的所有锁,也不会释放资源

线程中止稍微好一点,因为它至少会尝试终止线程清理器,并且锁有机会被释放

要正确地做到这一点,您确实需要线程的代码在终止时进行协作。事件、信号量甚至线程检查的简单bool值可能就足够了


最好重新设计您的解决方案,使其具有消息队列,并在单独的线程上处理它们。特殊消息可能只是清空队列。

在没有可靠方法终止线程的情况下启动线程是一种不好的做法。挂起/中止是终止线程的不可靠方法之一,因为您可能会在破坏整个程序的状态下终止线程,并且无法避免它的发生

您可以在此处看到如何安全地终止线程:

如果“用户”给你一个在线程中运行的方法,那么用户也应该给你一个停止代码运行的方法。将其视为一种契约:您向用户承诺您将调用stop方法,他们承诺stop方法将实际停止线程。如果您的用户违反了该合同,那么他们将对出现的问题负责,这很好,因为您不想对用户的错误负责:)

请注意,我不能强制函数的程序员捕获ThreadAbortException

由于挂起/中止是不好的做法,程序员不需要捕获
ThreadAbortException
,但是他们应该捕获
ThreadInterruptedException
,作为其“契约”的一部分

请记住,您需要担心两种情况:

  • 线程正在执行一些代码
  • 线程处于阻塞状态
  • 在线程正在执行某些代码的情况下,您所能做的就是通知线程它可以退出,并等待它处理通知。您也可以跳过等待,假设您泄漏了一个资源,在这种情况下,这又是用户的错,因为他们没有设计停止方法来及时终止线程


    如果线程处于阻塞状态且未阻塞通知构造(即信号量、手动重置事件等),则应调用
    thread.Interrupt()
    要使其脱离阻塞状态-用户必须处理
    ThreadInterruptedException

    您的应用程序和
    函数
    来自的任何地方之间需要某种取消协议。然后,您可以在
    函数
    和消息循环之间共享某种取消令牌。如果消息循环识别出需要停止
    函数
    ,则通过设置必须在适当场合由函数测试的令牌来发出信号。最简单的方法是共享一个条件变量,该变量可以从消息循环中自动设置,也可以从
    函数中自动读取


    我会考虑使用适当的异步IO模式结合.NETFramework提供的框,以及适当的取消机制。

    So.<代码>函数< /C> >是指您几乎没有控制的代码?这是典型的第三方库。大多数情况下,它们没有内置的功能来优雅地终止长时间运行的操作。因为你不知道这些功能是如何实现的,所以你只有很少的选择。事实上,您唯一有保证的安全选项是在它们自己的过程中加速这些操作,并通过WCF与它们通信。这样,如果您需要突然终止操作,您只需终止进程。终止另一个进程不会破坏当前进程的状态,就像您在当前进程内的线程上调用

    Thread.Abort

    我们缺少什么吗?将while(true)、while(keeploping)更改为while(keeploping),然后在循环内部,如果您检测到未将其设置为false,线程将优雅地完成???我刚刚检查了异步I/O,它似乎只有在我知道预期的消息以及确定没有其他消息可以到达的情况下才有意义。为了m