刚接触线程,需要帮助使静态变量与后台工作线程安全

本文关键字:线程 变量 后台 工作 安全 静态 帮助 接触 | 更新日期: 2023-09-27 18:08:45

正如标题所示,我是线程概念的新手,我正在学习。我正在做一个与3D打印机有关的研究项目。我需要与两个硬件进行交互:一个上下移动的小舞台,以及一个力传感器,它可以检测到舞台上的物体何时与传感器接触,从而作为停止移动舞台的信号。正如我所说的,我对整个线程概念是新的,所以我甚至不确定我的设计是否正确,如果我应该使用backgroundworker或Thread类,如何确保线程安全,等等。

我在c#中使用Windows窗体编写程序,并决定在Visual Studio/中使用两个后台worker控件。NET框架,一个用来监控力传感器的读数,另一个用来控制舞台的上下移动。

它必须快速和准确;当检测到预定义的传感器值时,工作台需要停止移动。我有两个静态类,一个ZStageControl静态类和一个ForceSensorControl静态类。

ForceSensorControl有一个叫做updatessensor()的方法,它返回力传感器的当前值,ZStageControl有一个私有的静态bool变量,forceDetected(默认设置为false),一个公共属性forceDetected获取/设置这个变量,还有一个叫做GoodToMove的方法。GoodToMove的定义如下:

    public static bool GoodToMove()
    {
            if (forceDetected == true ||
                Position() < MinHeight ||
                Position() > MaxHeight)
                return false;
            else
                return true;
    }

我的sensor update backgroundworker dowork代码定义如下:

    private void sensorUpdateBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        double currentForceValue;
        while (ForceSensorControl.IsConnected() == true)
        {
            if (worker.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                try
                {
                    currentForceValue = Double.Parse(ForceSensorControl.UpdateSensor());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    disconnectForceSensor();
                    return;
                }
                if (currentForceValue >= forceSensorStopValue)
                {
                    if (this.ForceDetected != null)
                    {
                        this.ForceDetected(this, 
                            new ForceDetectedEventArgs(ZStageControl.Position(), currentForceValue));
                    }
                }
                else if (ZStageControl.ForceDetected == true)
                    ZStageControl.ForceDetected = false;
                forceSensorValueLabel.Text = currentForceValue.ToString() + "g";
            }
        }
    }

所以只要传感器保持连接,不断循环并更新力传感器值。如果它检测到正确的力值,它将触发ForceDetected事件。如果它读取的值小于力传感器停止值,但ForceDetected仍然设置为true,则它将简单地设置为false(因为当检测到力时,它将阻止舞台移动,然后将其返回到默认位置,因此它应该重置力检测变量)。

事件码定义如下:

    public void FormMain_ForceDetected(object sender, ForceDetectedEventArgs e)
    {
        if (ZStageControl.ForceDetected == true)
            return;
        ZStageControl.ForceDetected = true;
        feedbackRichTextBox.Text += "'nForce Detected at position " +
            e.ForceDetectedPosition.ToString() + " with a value of " +
            e.ForceDetectedValue.ToString() + "'n";
        ScrollToEndOfFeedbackBox(feedbackRichTextBox);
        soundPlayer.Play();
    }

向上或向下移动Z-Stage的线程定义如下:

    private void zStageMoveBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        ZStageMoveDirections direction = (ZStageMoveDirections)e.Argument;
        while (ZStageControl.IsConnected == true)
        {
            if (worker.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                System.Threading.Thread.Sleep(zStageSpeed);
                if (direction == ZStageMoveDirections.Down)
                {
                    ZStageControl.MoveDown(true);
                }
                if (direction == ZStageMoveDirections.Up)
                {
                    ZStageControl.MoveUp(true);
                }
                zStagePositionUpdateLabel.Text = ZStageControl.Position().ToString();
            }
        }
    }

为Z-Stage移动调用DoWork事件的代码由if语句控制,该语句检查ZStageControl.GoodToMove()是否为真。因此,当GoodToMove()返回true时,Z-Stage线程可以触发。

我遇到的问题是,我不确定我是否在设计这个权利,如果我正确使用后台工作者,我知道我的变量不是线程安全的,因为在某些点GoodToMove()返回true,其他时候它返回false,即使没有明显的力量被检测到。它似乎有自己的想法。我对线程安全一无所知。我应该简单地使用线程类而不是后台工作者,是否有一定的方法来确保forceDetected变量/GoodToMove()方法在这些线程中正常运行?

刚接触线程,需要帮助使静态变量与后台工作线程安全

我认为你的方法本身就有缺陷。

你似乎正在设计一个具有不断循环监视器的系统,然后当你想要执行"移动"时检查该监视器。"

这在本质上是有问题的,因为你在你的安全检查操作和你的移动操作之间创建了一个竞争条件。

考虑一下:

1       // check if move is ok -- PASS
(async) // move suddenly becomes not ok!
2       // move is executed

相反,您应该将此问题视为完全同步的(因为验证检查和执行应该完全是原子的)。每当请求移动时,您应该检查它是否被允许,然后决定是否执行。

1 // exclusive lock
2 // check if move is ok -- PASS
3 // execute move
4 // release lock