如何使timer2和timer3同时工作但不同步?

时间:2014-09-15 11:35:11

标签: c# .net winforms

我有一个timer3 tick事件:

private void timer3_Tick(object sender, EventArgs e)
        {
            pictureBox1.Invalidate();
        }

Timer3间隔设置为10ms。它将进入pictureBox1的绘制事件并绘制一些东西。

然后我有timer2 tick事件:

private void timer2_Tick(object sender, EventArgs e)
        {
            label1.Visible = true;
            if (counter == 200)
            {
                timer2.Enabled = false;
                return;
            }
            counter += 1;
            distance = (float)counter;
            CloudEnteringAlert.cloudalert(bitmapwithclouds, distance);
            double d = double.Parse(CloudEnteringAlert.cloudsdistance.Text, CultureInfo.InvariantCulture);
            string s = string.Format("{0:0.0}", d);
            if (CloudEnteringAlert.cloudsfound == true)
            {
                label2.Visible = true;
                timer1.Enabled = true;
                listBox1.Items.Add("Cloud detected at: " + CloudEnteringAlert.cloudsdistance.Text + " Kilometers from the coast");
                timesdetectedclouds += 1;
                label2.Text = timesdetectedclouds.ToString();
                if (CloudEnteringAlert.cloudsdistance.Text == "0")
                {

                }
                else
                {
                    if (CloudEnteringAlert.cloudsfound == false)
                    {

                    }
                }
            }
            else
            {
                double dd = double.Parse(CloudEnteringAlert.cloudsdistance.Text, CultureInfo.InvariantCulture);
                string ss = string.Format("{0:0.0}", d);
                listBox1.Items.Add("Cloud not detected at: " + CloudEnteringAlert.cloudsdistance.Text + " Kilometers from the coast");
                timesnotdetectedclouds += 1;
                label4.Text = timesnotdetectedclouds.ToString();
            }
        }

timer2 interval设置为1000ms

问题是当timer2和timer3同时工作时,pictureBox1的paint事件中的绘图变得非常慢,只有当timer2停止时,timer3才会以10ms的速度运行。

问题是如何使两个计时器同时工作但每个计时器都有自己的实时时间?将timer3放入后台工作者?如果是这样,如何与背景工作者一起做?

这是pictureBox1绘画事件:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            anglecounter += 1;
            DrawLine(e.Graphics, anglecounter);
            if (null != mImage)
            {
                e.Graphics.DrawImage(mImage, mRect);
            }
            DrawRectangle(e.Graphics);
        }

这是DrawLine方法:

private void DrawLine(Graphics g, double angle)
        {

            Pen pen = new Pen(Color.Red, 2f);
            int r = pictureBox1.Size.Width / 2;
            int X1 = pictureBox1.Size.Width / 2;
            int Y1 = pictureBox1.Size.Height / 2;
            Point pStart = new Point(X1, Y1);
            int X2 = (int)(X1 + r * Math.Cos((double)angle * Math.PI / 180));
            int Y2 = (int)(Y1 + r * Math.Sin((double)angle * Math.PI / 180));
            Point pEnd = new Point(X2, Y2);
            g.DrawEllipse(new Pen(Color.Red, 2f), 0, 0, pictureBox1.Size.Width, pictureBox1.Size.Height);
            Rectangle rec = new Rectangle(0, 0, pictureBox1.Size.Width, pictureBox1.Size.Height);
            path = new GraphicsPath();
            path.AddPie(rec, (int)angle, -50);
            PathGradientBrush brush = new PathGradientBrush(path);
            brush.CenterPoint = pStart;
            brush.CenterColor = Color.LightGreen;
            brush.SurroundColors = new Color[] { Color.Empty };
            g.FillPath(brush, path);

        } 

DrawRectangle方法:

private void DrawRectangle(Graphics e)
        {
            using (Pen pen = new Pen(Color.Red, 2))
            {
                e.DrawRectangle(pen, mRect);
            }
        }

绘制矩形,如果我想要在pictureBox1上手工绘制一个矩形。 drawline方法像多普勒雷达一样绘制,我想让它一直动画/移动aorund,这就是为什么我使用timer3 10ms并使pictureBox1无效。

timer2做了别的事情,它正在做另一项任务,我需要在雷达上检测一些像素。

2 个答案:

答案 0 :(得分:1)

您可以使用System.Timers.Timer类,它是一个线程安全的计时器。

关于您的UI修改,您可以使用Control.Invoke在线程安全环境中修改UI的部分内容。

这是一个小例子(对于后期添加感到抱歉):

private System.Timers.Timer timer2 = new System.Timers.Timer(1000),
                            timer3 = new System.Timers.Timer(10);
public void Init()
{
    timer3.Elapsed += (sender, args) =>
    {
        // update your UI from the timer's thread
        pictureBox1.Invoke(
            new Action( 
                () =>
                {
                    pictureBox1.Invalidate();
                }
            )
        );
    };

    timer2.Elapsed += (sender, args) =>
    {
        // Do other stuff with the UI by calling 
        // the appropriate Control invoke methods
    };

    timer2.Enabled = timer3.Enabled = true;
}

答案 1 :(得分:0)

当您在UI线程中工作时,不可能:
UI只能从该线程访问,因为一个线程一次只能做一件事,你不能并行执行它们。

你能做的只是使用10ms计时器,但计算迭代次数,每1000ms执行一次“timer2 logic”......

也许你可以解释一下你的目标,因为我觉得你走错了路 - pictureBox1.Invalidate()通过计时器每隔10毫秒“闻起来有点”......