C# MessageBox和while循环C

C# MessageBox和while循环C,c#,while-loop,messagebox,C#,While Loop,Messagebox,我正在修改现有的C代码以操纵活塞。每隔30毫秒,我会通过一个事件直接反馈这个活塞的位置。该值存储在一个全局变量中,我使用该变量获取活塞的当前位置 我试图实现的目标是:对于给定的距离输入a->C,我希望活塞在95%的距离a->B以全速行驶,然后在剩余的5%的距离B->C以较慢的速度行驶 我可以访问一个命令,该命令定义活塞的速度和目的地:posvelocity,destination 但是,如果我编写该代码: pos(fullSpeed,B); pos(reducedSpeed, C); 活塞直接

我正在修改现有的C代码以操纵活塞。每隔30毫秒,我会通过一个事件直接反馈这个活塞的位置。该值存储在一个全局变量中,我使用该变量获取活塞的当前位置

我试图实现的目标是:对于给定的距离输入a->C,我希望活塞在95%的距离a->B以全速行驶,然后在剩余的5%的距离B->C以较慢的速度行驶

我可以访问一个命令,该命令定义活塞的速度和目的地:posvelocity,destination

但是,如果我编写该代码:

pos(fullSpeed,B);
pos(reducedSpeed, C);
活塞直接从全速转到减速

我尝试使用while循环来比较活塞的当前位置和目标位置,但是,在进入while循环时,存储活塞位置的变量不再更新

但是,我注意到,通过在中间抛出一个MessageBox,位置值会不断更新,我只需单击ok即可启动第二个命令

pos(fullSpeed,B);
MessageBox.show("Wait");
pos(reducedSpeed, C);
我想知道为什么while循环停止了位置变量的更新,而MessageBox没有。我的意思是,只要我不点击ok按钮,这个框就在这里阻止我做任何事情,这对我来说是一种暂时的循环行为。有没有其他方法可以代替MessageBox

对于C语言我几乎一无所知,也没有支持。我试图查看文档,但没有找到答案,我可能错过了。任何线索都是受欢迎的

编辑:我没有这段代码的文档,也几乎没有注释。以下是我收集到的信息,希望能有所帮助:

要移动活塞,调用taht函数:

MyEdc.Move.Pos(control, speed, destination, ref MyTan);
控件只是定义我们驾驶的距离或负载,它是一个枚举,我不知道MyTan做什么。我只知道MyEdc.Move.Pos返回一个错误代码

如果我看一下pos的定义,我会被重定向到类

public DoPEmove Move;
其中包括:

public DoPE.ERR Pos(DoPE.CTRL MoveCtrl, double Speed, double Destination, ref short Tan);
DoPE.ERR也是一个类型枚举。但是,我无法找到名为Pos的函数的定义。它是否在包含的.dll中

以下代码允许我在不使用全局变量的情况下访问活塞的位置:

private int OnData(ref DoPE.OnData Data, object Parameter)
    {
      if (Data.DoPError == DoPE.ERR.NOERROR)
      {
        DoPE.Data Sample = Data.Data;
        Int32 Time = Environment.TickCount;
        if ((Time - LastTime) >= 300 /*ms*/)
        {
          LastTime = Time;
          string text;
          text = String.Format("{0}", Sample.Time.ToString("0.000"));
          guiTime.Text = text;
          text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_S].ToString("0.000"));
          guiPosition.Text = text;
          text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_F].ToString("0.000"));
          guiLoad.Text = text;
          text = String.Format("{0}", Sample.Sensor[(int)DoPE.SENSOR.SENSOR_E].ToString("0.000"));
          guiExtension.Text = text;
        }
      }
      return 0;
    }
这叫做使用

MyEdc.Eh.OnDataHdlr += new DoPE.OnDataHdlr(OnData);

我意识到我对软件如何运行知之甚少,这对你来说是多么令人沮丧。如果你认为这是一个失败的原因,没问题,我会尝试Timothy Jannace解决方案,如果它对我没有帮助,我会坚持使用MessageBox解决方案。我只是想知道为什么MessageBox允许我实现我的目标,但是while循环没有,以及如何在这里利用它

我相信您要做的是添加一个呼叫:

Application.DoEvents();
这将允许您的应用程序处理已发布的消息事件,这将允许更新该全局变量

我只是想知道为什么MessageBox允许我实现我的目标,但是while循环没有,以及如何在这里利用它


之所以有效,是因为您让WndProc有机会处理已发送到应用程序的事件。这不是调用MessageBox.Show;,的预期功能;,但这是一个后果。您可以通过调用Application.DoEvents执行相同的操作;在不中断消息框的情况下。

如果使用事件,则可能存在并发问题。特别是每30毫秒就要举行一次活动

处理并发性的一种非常简单的方法是使用锁对象来防止不同线程同时使用有争议的资源:

class MyEventHandler
{
    private object _lockObject;

    MyEventHandler()
    {
        _lockObject = new object();
    }

    public int MyContestedResource { get; }

    public void HandleEvent( object sender, MyEvent event )
    {
        lock ( _lockObject )
        {
            // do stuff with event here
            MyContestedResource++;
        }
    }
}
请记住,这是非常简单的,绝不是完美的在每一个场景。如果你提供更多关于这些活动是如何举办的以及你正在做什么的信息,人们将能够提供更多的帮助

编辑:

使用您为Pos方法发布的签名,我能够找到您正在使用的库的文档:

只有在转到定义时才能看到方法签名的原因是库已编译到dll中。实际上,不管怎么说,它都是不太有用的,因为它看起来像是一个围绕本地C或C++代码的C包装器。 无论如何,我希望这些文件对你有帮助。如果你看第20页,有一些关于做动作的指示。这对一个新的程序员来说是一个挑战,但你可以做到。我建议您避免使用事件处理程序来驱动逻辑,而是坚持使用命令的同步版本。使用同步命令时,代码的操作方式应与读取的方式相同

我尝试使用while循环来比较 然而,当进入while时,活塞与目标目标一致 循环,存储活塞位置的变量不会更新 再也没有了

当您在While循环中时,您的a pp无法再接收和处理反馈事件

一种可能的解决方案是使用/像这样:

private const int fullSpeed = 1;
private const int reducedSpeed = 2;

private int currentPistonPositon = 0; // global var updated by event as you described

private async void button1_Click(object sender, EventArgs e)
{
    int B = 50;
    int C = 75;

    pos(fullSpeed, B);

    await Task.Run(() =>
        {   // pick one below?

            // assumes that "B" and "currentPistonPosition" can actually be EXACTLY the same value
            while (currentPistonPositon != B) 
            {
                System.Threading.Thread.Sleep(25);
            }

            // if this isn't the case, then  perhaps when it reaches a certain threshold distance?
            while (Math.Abs(currentPistonPositon - B) > 0.10)
            {
                System.Threading.Thread.Sleep(25);
            }
        });

    pos(reducedSpeed, C);
}
private void button1_Click(object sender, EventArgs e)
{
    int B = 50;
    int C = 75;

    GotoPosition(fullSpeed, B);
    GotoPosition(reducedSpeed, C);
}

private async void GotoPosition(int speed, int position)
{
    pos(speed, position);

    await Task.Run(() =>
    {
        while (Math.Abs(currentPistonPositon - position) > 0.10)
        {
            System.Threading.Thread.Sleep(25);
        }
    });
}
注意,button1\u Click方法签名已标记为async。代码将等待任务内的while循环完成,同时由于等待而仍在处理事件消息。只有这样,它才会转到第二个pos呼叫


谢谢你的回答!它就像一个符咒!很好地抓住了这个机会 精确值。我学到了很多,我确信async/await组合是 在未来将会非常有用格言

如果工作正常,那么你可能需要考虑重构代码并制作自己的Goto位置方法:

private const int fullSpeed = 1;
private const int reducedSpeed = 2;

private int currentPistonPositon = 0; // global var updated by event as you described

private async void button1_Click(object sender, EventArgs e)
{
    int B = 50;
    int C = 75;

    pos(fullSpeed, B);

    await Task.Run(() =>
        {   // pick one below?

            // assumes that "B" and "currentPistonPosition" can actually be EXACTLY the same value
            while (currentPistonPositon != B) 
            {
                System.Threading.Thread.Sleep(25);
            }

            // if this isn't the case, then  perhaps when it reaches a certain threshold distance?
            while (Math.Abs(currentPistonPositon - B) > 0.10)
            {
                System.Threading.Thread.Sleep(25);
            }
        });

    pos(reducedSpeed, C);
}
private void button1_Click(object sender, EventArgs e)
{
    int B = 50;
    int C = 75;

    GotoPosition(fullSpeed, B);
    GotoPosition(reducedSpeed, C);
}

private async void GotoPosition(int speed, int position)
{
    pos(speed, position);

    await Task.Run(() =>
    {
        while (Math.Abs(currentPistonPositon - position) > 0.10)
        {
            System.Threading.Thread.Sleep(25);
        }
    });
}
可读性将大大提高

您甚至可以变得更加花哨,在while循环中引入超时概念。现在,您的代码可以执行以下操作:

private void button1_Click(object sender, EventArgs e)
{
    int B = 50;
    int C = 75;

    if (GotoPosition(fullSpeed, B, TimeSpan.FromMilliseconds(750)).Result)
    {
        if (GotoPosition(reducedSpeed, C, TimeSpan.FromMilliseconds(1500)).Result)
        {
            // ... we successfully went to B at fullSpeed, then to C at reducedSpeed ...
        }
        else
        {
            MessageBox.Show("Piston Timed Out");
        }
    }
    else
    {
        MessageBox.Show("Piston Timed Out");
    }

}

private async Task<bool> GotoPosition(int speed, int position, TimeSpan timeOut)
{
    pos(speed, position); // call the async API

    // wait for the position to be reached, or the timeout to occur
    bool success = true; // assume we have succeeded until proven otherwise
    DateTime dt = DateTime.Now.Add(timeOut); // set our timeout DateTime in the future
    await Task.Run(() =>
    {
        System.Threading.Thread.Sleep(50); // give the piston a chance to update maybe once before checking?
        while (Math.Abs(currentPistonPositon - position) > 0.10) // see if the piston has reached our target position
        {
            if (DateTime.Now > dt) // did we move past our timeout DateTime?
            {
                success = false;
                break;
            }
            System.Threading.Thread.Sleep(25); // very small sleep to reduce CPU usage
        }
    });
    return success;
}

pos机的代码是什么?这是一种异步方法吗?您试图在文档中找到什么?在不了解pos的情况下,我们真的什么也说不出来。显然,这是一个异步调用。是否存在返回值或重载,以通知您是否达到该位置?职位更新是如何设计的?显然,它和你的while运行在同一个线程上。所以,while只是阻止了更新。同样,如果你对图书馆一无所知,就不可能说出一些有用的东西。请提供posThank you的代码作为你的答案!它就像一个符咒!很好地抓住了确切的价值。我学到了很多,我相信async/await组合在将来会非常有用!活塞是否始终通过事件报告其位置,还是仅在响应pos呼叫时报告,然后直到停止移动?非常感谢您的编辑,我今天仍将执行它!非常感谢您的解释!只需添加Application.DoEvents就可以了!我会选择@Idle\u Mind解决方案,因为它使代码更容易阅读,但非常感谢您花时间向我解释发生了什么,并提供了一个解决方案。谢谢您的回答Timothy!如果我明白你的代码是怎么回事,我似乎无法正确地实现它。很抱歉,这里的技能非常有限。事实上,我不太了解这里发生的事情,尤其是所有的事件,以及它们被调用的地方,这没有帮助。非常感谢你对我的问题的投入。我一直在寻找文档,但即使是机器制造商也没有,所以我没有在网上努力寻找。我相信这会很有帮助,我会听从你的建议,尽量坚持使用sync命令!