线程不会作为受控的单独线程运行

Posted

技术标签:

【中文标题】线程不会作为受控的单独线程运行【英文标题】:Thread wont run as a controlled seperated thread 【发布时间】:2018-07-15 04:47:34 【问题描述】:

我有一个测量硬件设备,我想通过课程来控制它。我希望能够启动和停止它并让它在自己的线程中进行测量。这样宽度为 2 的按钮我可以开始和停止采样测量,因此我创建了 MeasurementsStart() 和 MeasurementsStop() 两者都是从 2 个按钮调用的。

当在函数 TakeMeasurements() 内部时,我结束 宽度 WorkThread.Abort(); VS2017,说不是所有的代码路径都返回一个值。

当我在适当的位置结束宽度“Throw new NotImplementedException”时,代码会编译它运行,但是当我按下 MeasurementsStart 按钮时,工作线程会继续运行,尽管程序的其余部分会冻结。

我不清楚我应该如何结束这个函数来获得这个开始/停止行为。

此处的实际测量代码已替换为随机数。

   Public static Class Measure
   
        public static List<double> Samples;
        private static Thread workThread;
        private static volatile bool stopThread = false;


        public static void MeasurementsStop()
        
            if (workThread != null)
            
                stopThread = true;
                workThread.Join(); // pauses till Thread exits.
                workThread = null;
            
        

        public static void MeasurementsStart()
        
            Samples = new List<double>();
            if (workThread == null)
            
                stopThread = false;
                workThread = new Thread(new ThreadStart(TakeMeasurements()));
                workThread.IsBackground = true;
                workThread.Start();
            
        

        private static ThreadStart TakeMeasurements()
        
            while (!stopThread )
            System.Console.Beep(200, 200);
               Samples.Add(new Random().Next(int.MinValue, int.MaxValue));
              System.Console.Beep(400, 200);
            
           workThread.Abort();
           //   throw new NotImplementedException();
        

【问题讨论】:

不要使用Abort 取消线程。 Abort是安全罩下的红色大开关,由两名手持钥匙的警官打开。使用 CancellationToken 检查操作是否需要终止。顺便说一句,static volatile bool stopThread 不是线程安全的。在 CancellationToken 之前人们使用 ManualResetEvent 和其他类似的构造,从不使用全局变量 如果您想在后台线程中进行定期测量,而不是无限的while 循环,请使用计时器。通常使用 Tasks 而不是原始线程,以便能够组合异步操作,并能够安全地处理它们的结果 - Samples 不是线程安全的。 ConcurrentQueue 可能会更好 那个'令牌'?是 bool stopThread,我可以删除“workThread.Abort() 但它仍然无法工作,我认为它应该在那里,但它已经是一个不工作的修复程序。 @PanagiotisKanavos,在这种情况下,必须在准备好后快速读取测量设备,但对于每个样本,它都会经历一个随机初始化时间。这就是为什么我没有使用计时器,而是使用循环检索。 CancellationToken 有效。它不会中止线程,这是一个非常严重的错误。代码检查是否请求取消并优雅地退出循环。已经有很多个重复的问题 【参考方案1】:

您的问题不在于取消线程,而在于您在主线程上运行TakeMeasurements() 函数。

在您的workThread = new Thread(new ThreadStart(TakeMeasurements())); 行中,您正在调用您的TakeMeasurements 函数(因为它的末尾有括号),而不是传递对该函数的引用作为启动新线程的位置。

TakeMeasurements函数签名更改为返回void(因为它没有返回),然后更改

workThread = new Thread(new ThreadStart(TakeMeasurements()));

workThread = new Thread(new ThreadStart(TakeMeasurements));

(注意不带括号)。

至于取消TakeMeasurements 线程(并假设您正在使用诸如TCP 之类的阻塞读取方法),您有两种方法。 您可以:

对阻塞调用设置一个超时,以便线程定期唤醒以检查stopThread,或者 使用CancellationToken,只要您的阻塞调用支持接受CancellationToken 作为参数。

两者都可以,但结构不同。如果您使用的阻止方法支持CancellationToken,那将是我的首选。

希望对你有帮助

【讨论】:

是的,现在它可以工作了,而且很有意义。我已经在考虑取消构造并重写了大部分内容,但也有点卡住了,谢谢!

以上是关于线程不会作为受控的单独线程运行的主要内容,如果未能解决你的问题,请参考以下文章

在单独的线程中运行 Tkinter 表单

Web Worker 是在主 ui android 线程还是单独的线程上运行?

QOpenGLWidget 和多线程

使用异步方法等待 Task.Run 不会在正确的线程上引发异常

如何使用 Java 在不同的线程上或作为不同的进程运行不同的 sql 查询

C++ 在 Windows API 中创建一个单独的线程,程序终止?