线程不会作为受控的单独线程运行
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
,那将是我的首选。
希望对你有帮助
【讨论】:
是的,现在它可以工作了,而且很有意义。我已经在考虑取消构造并重写了大部分内容,但也有点卡住了,谢谢!以上是关于线程不会作为受控的单独线程运行的主要内容,如果未能解决你的问题,请参考以下文章
Web Worker 是在主 ui android 线程还是单独的线程上运行?
使用异步方法等待 Task.Run 不会在正确的线程上引发异常