C#中的物理项目:线程和测量时间的问题

时间:2013-05-28 04:13:23

标签: c# .net multithreading timer stopwatch

我正在尝试制作物理项目的一些问题。 它基本上是一个自由落体模拟器。我设定了重力加速度和高度,程序应该模拟下降。 问题在于时间错了,不知道为什么。我正在使用秒表课来测量时间。

以下是代码:

FrmMain.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Threading;
using System.Diagnostics;

namespace Physics
{
    public partial class FrmMain : Form
    {
        public Settings config = new Settings();

        public float displacement = 0f;

        public Stopwatch timer = new Stopwatch();
        public float timeElapsed; //in Seconds

        public Thread thread;

        public FrmMain()
        {
            InitializeComponent();

            //New thread (Drawing)
            thread = new Thread(new ThreadStart(Drawing));
            thread.IsBackground = true;
            thread.Start();

            this.KeyDown +=new KeyEventHandler(FrmMain_KeyDown);
        }

        private void Drawing()
        {
            try
            {
                while (true)
                {
                    if (config.objectPos.Y < config.sizeBitmap.Height)
                        timer.Start();
                    else
                        timer.Stop();
                    Bitmap screen = new Bitmap(this.pboxScreen.Width,
                                               this.pboxScreen.Height);
                    SendScreen(screen);
                }
            }
            catch (ThreadAbortException tae)
            {
                Console.WriteLine(tae.Message);
            }
        }

        private void SendScreen(Bitmap Screen)
        {
            if (pboxScreen.InvokeRequired)
            {
                pboxScreen.Invoke(new MethodInvoker(delegate()
                {
                    this.SendScreen(Screen);
                }));
            }
            else
            {   //Converting Milliseconds to Seconds
                timeElapsed = timer.ElapsedMilliseconds / 1000f;
                //Check if object isn't in the ground
                if (config.objectPos.Y < config.sizeBitmap.Height)
                 {
                    displacement -= config.objectPos.Y;
                    config.objectPos.Y = config.objectPos.Y + 0.5f * 
                                         config.acceleration * 
                                         timeElapsed * timeElapsed;
                    displacement += config.objectPos.Y;
                }

                Graphics g = Graphics.FromImage(Screen);
                g.Clear(Color.White);

                //New rectangle
                Rectangle rec = new Rectangle((int)config.objectPos.X, 
                                               (int)config.objectPos.Y, 5, 5);
                g.FillRectangle((new Pen(Color.DarkRed)).Brush, rec);
                g.DrawRectangle(new Pen(Color.Red, 2.0f), rec);

                g.Dispose();

                //Update txtbox (textbox)
                txtboxX.Text = config.objectPos.X.ToString();
                txtboxY.Text = config.objectPos.Y.ToString();
                txtboxTempo.Text = timeElapsed.ToString();
                txtboxD.Text = displacement.ToString();

                pboxScreen.Image = Screen;
            }
        }

        void FrmMain_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Space:
                    if (config.objectPos.Y >= config.sizeBitmap.Height)
                    {
                        config.objectPos.Y -= 100;
                        timer.Reset();
                    }
                    break;
            }
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread.IsAlive) thread.Abort();
        }
    }
}

Settings.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Physics
{
    public class Settings
    {
        public Size sizeBitmap; //bitmap resolution
        public PointF objectPos; //Initial Position
        public float acceleration;

        public Settings()
        {
            sizeBitmap.Width = 560;
            sizeBitmap.Height = 420;
            objectPos.X = 560f / 2f;
            objectPos.Y = 420f / 2f;
            acceleration = 9.8f;
        }

    }
}

还有另一个问题,取决于高度,物体不会在没有中断的情况下掉落,它会保持在相同的位置几个,但是明显的毫秒。我认为这是一个线程问题,因为我有一段时间不使用它,所以我可能会遗漏一些东西。

我以米为单位测量高度,因此objectPos.Y = 420f / 2f表示高度为210米。对于这个高度,物体应该花费大约6.5秒才能击中地面,在我的程序中花费的时间不到1秒,所以我认为有时间测量问题。

我用均匀的引力场计算高度,没有空气阻力表达式:

  

H(T)= H0 + 0.5 * G * T 2

其中: h(t)是相对于时间的高度, h0 初始高度, g 由于重力引起的加速度< em> t 经过的时间

非常感谢任何帮助。 感谢。

2 个答案:

答案 0 :(得分:1)

我相信您的问题可能就在

        config.objectPos.Y = config.objectPos.Y + 0.5f * 
                             config.acceleration * 
                             timeElapsed * timeElapsed;

时间t = t-sub-k(config.objectPos.Y)处的YPosition是时间t-sub-k处的高度。如果t是总经过时间,那么这等于 初始 Y位置(时间高度t = 0)+ 1/2 gt ^ 2,而不是最后 Y位置。

你正在做的是采取最后的Y位置(上次计算的高度,并在从时间t = 0到t = t-sub-k的经过时间内增加高度下降。所以它不是不知道它下降得太快了。

将初始Y位置只读属性添加到您的设置构造中,并且不要更新或修改它。

修改代码以使用它,如下所示:

        config.objectPos.Y = config.InitialY + 0.5f * 
                             config.acceleration * 
                             timeElapsed * timeElapsed;

答案 1 :(得分:0)

我认为你的公式错了。 h0应该是初始速度(在你的情况下是0米/秒),它应该与时间相乘。

这是正确的from This is the for

所以说过,Vi * t总是0,因为你的初始速度是0.剩下的是0.5 * 9.8 * timeElapsed * timeElapsed。

            config.objectPos.Y = 0 //initial velocity
                + 0.5f * config.acceleration * timeElapsed * timeElapsed;

此外,objectPost.Y应始终从0米开始,因为它从顶部开始,它将会下降。

您可以参考此控制台应用代码。运行它并查看比较的时间并将其与results in

进行比较

应该是1.32秒。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Physics_16783733
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass c = new MyClass();
        }
    }

    public class MyClass
    {
        public Settings config = new Settings();

        public Stopwatch timer = new Stopwatch();
        public float timeElapsed; //in Seconds

        public Thread thread;

        static ManualResetEvent control;

        public MyClass()
        {
            control = new ManualResetEvent(false);
            //New thread (Drawing)
            thread = new Thread(new ThreadStart(Drawing));
            thread.IsBackground = true;
            thread.Start();

            control.WaitOne();
        }

        public void Drawing()
        {
            try
            {
                while (true)
                {
                    if (config.objectPos.Y < config.sizeBitmap.Height)
                    {
                        timer.Start();
                    }
                    else
                    {
                        timer.Stop();
                        control.Set();
                    }
                    //Bitmap screen = new Bitmap(this.pboxScreen.Width, this.pboxScreen.Height);
                    SendScreen();
                }
            }
            catch (ThreadAbortException tae)
            {
                Console.WriteLine(tae.Message);
            }
        }

        private void SendScreen()
        {
            timeElapsed = timer.ElapsedMilliseconds / 1000f; //Converting Milliseconds to Seconds

            if (config.objectPos.Y < config.sizeBitmap.Height) //Check if object isn't in the ground
            {
                //formula used is in http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm
                config.objectPos.Y = 0 //initial velocity
                    + 0.5f * config.acceleration * timeElapsed * timeElapsed;
            }

            //Update txtbox (textbox)
            Console.WriteLine("Object position Y: " + config.objectPos.Y.ToString());
            Console.WriteLine("Time elapsed     : " + timeElapsed.ToString()); //using the data from http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm, time elapsed should be 1.32 seconds
        }
    }

    public class Settings
    {
        //I used data from http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm
        //where the given is:

        //vi = 0.0 m/s
        //d = -8.52 m
        //a = - 9.8 m/s2

        public Size sizeBitmap; //height of the place where the object will start free falling
        public PointF objectPos; //Initial Position
        public float acceleration;

        public Settings()
        {
            sizeBitmap.Height = 8.52;
            objectPos.Y = 0;
            acceleration = 9.8f;
        }

    }

    public struct PointF
    {
        public float Y { get; set; }
    }

    public struct Size
    {
        public double Height { get; set; }
    }
}