【发布时间】:2015-06-11 12:20:26
【问题描述】:
我目前正在编写一个控制测量设备定位的应用程序。由于涉及的硬件,我需要在运行电动机时不断地轮询当前位置值。我正在尝试构建负责此的类,以便它在后台线程上进行轮询,并在达到所需位置时引发事件。这个想法是轮询不会阻塞应用程序或 GUI 的其余部分。我想使用新的 Threading.Task.Task 类来为我处理所有后台线程管道。
我还没有硬件,但是已经构建了一个测试存根来模拟这种行为。但是当我像这样运行应用程序时,GUI 仍然会阻塞。请参阅下面代码的简化示例(不完整且未使用单独的类进行设备控制)。代码有一系列测量步骤,应用程序必须定位并测量每个步骤。
public partial class MeasurementForm: Form
{
private MeasurementStepsGenerator msg = new MeasurementsStepGenerator();
private IEnumerator<MeasurementStep> steps;
// actually through events from device control class
private void MeasurementStarted()
{
// update GUI
}
// actually through events from device control class
private void MeasurementFinished()
{
// store measurement data
// update GUI
BeginNextMeasurementStep();
}
private void MeasurementForm_Shown(object sender, EventArgs e)
{
steps = msg.GenerateSteps().GetEnumerator();
BeginNextMeasurementStep();
}
...
...
private void BeginNextMeasurementStep()
{
steps.MoveNext();
if (steps.Current != null)
{
MeasurementStarted();
MeasureAtPosition(steps.Current.Position);
}
else
{
// finished, update GUI
}
}
// stub method for device control (actually in seperate class)
public void MeasureAtPosition(decimal position)
{
// simulate polling
var context = TaskScheduler.FromCurrentSynchronizationContext();
Task task = Task.Factory.StartNew(() =>
{
Thread.Sleep(sleepTime);
}, TaskCreationOptions.LongRunning)
.ContinueWith(_ =>
{
MeasurementFinished();
}, context);
}
}
我希望任务在后台线程上运行 Thread.Sleep 命令,以便控制立即返回到主线程并且 GUI 不会被阻塞。但是 GUI 仍然被阻止。就像任务在主线程上运行一样。关于我在这里做错了什么有什么想法吗?
谢谢
【问题讨论】:
-
我已经用一些繁重的算法而不是 Thread.Sleep 对此进行了测试,然后一切正常。 Thread.Sleep 是否总是在主线程上工作?我希望它可以在当前线程中工作。
-
我的意思是我希望它阻塞任务线程,而不是 UI 线程。
-
我发现无论我使用繁重的算法还是 Thread.Sleep(),使用 ContinueWith() 串联运行任务都会阻塞 UI。当您并行运行任务时,对于繁重的算法它不会这样做,但我不能这样做,我的任务必须按顺序运行。
-
我对 .NET 一无所知。但是,我已经制作了许多 PC 嵌入式系统接口,我知道的一件事是 PC 操作系统不是实时的。任何需要及时更新的事情都需要在您可以更好地控制正在发生的事情的环境中完成,这不是 .NET 与 Thread.Sleep。您说有电机 - 如果您的代码在一段时间内没有响应,这是否会对人或物体造成安全隐患?
-
无法重新创建。一些问题:您确定它是因为 Thread.Sleep (或您在该任务中拥有的任何东西)而挂起的吗?如果你打破了,你会在那里得到一个断点吗?打开 Debug > Windows > Threads 是否可以看到挂起的线程?