跨线程操作对于使图形对象无效无效

时间:2013-10-18 01:18:56

标签: c# winforms

我正在尝试使用Timer创建每500ms重绘一次的图形,但我一直在进行跨线程操作。有人可以告诉我为什么会这样吗?

错误:

Cross-thread operation not valid: Control 'GraphicsBox' accessed from a thread other than the thread it was created on.

我正在使用WinForms,并在主窗体中有一个名为“GraphicsBox”的PictureBox:

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.Diagnostics;
using System.Threading;

namespace NamespaceName
{
    public partial class FormName : Form
    {
        Graphics g;

        public FormName()
        {
            InitializeComponent();
            System.Timers.Timer t = new System.Timers.Timer();
            t.Interval = 500;
            t.Enabled = true;
            t.Elapsed += (s, e) => this.GraphicsBox.Invalidate(true);
        }

        private void FormName_Load(object sender, EventArgs e)
        {
            this.GraphicsBox.Paint += new PaintEventHandler(OnPaint);
        }

        protected void OnPaint(object sender, PaintEventArgs e)
        {
            g = e.Graphics;
            //Draw things
        }
    }
}

我有什么方法可以从计时器的'tick'(或'elapsed')中触发OnPaint事件?我相信会做到这一点。我所要做的就是重绘图形对象,我会改变代码中的内容,使其以不同的方式绘制。

2 个答案:

答案 0 :(得分:1)

这里的主要问题是至少有3个名为Timer的类可能更多(在不同的名称空间中,但具有不同的行为)。您正在使用一个回调工作线程,并且由于线程关联性,UI控件不喜欢它。

如果切换到System.Windows.Forms.Timer,它将调用UI线程上的回调(可能是通过同步上下文,但我想它可能是直接使用消息循环实现的)。这不是一个跨线程操作,并且可以正常工作。

答案 1 :(得分:1)

您在错误的线程上调用GraphicsBox对象,在另一个(后台)线程上调用System.Timers.Timer.Elapsed

你可以 -

a)切换到使用System.Windows.Forms.Timer,它将与GraphicsBox

在同一个主题上运行

b)快速而讨厌 -

t.Elapsed += (s, e) => this.Invoke(new MethodInvoker(delegate(){ this.GraphicsBox.Invalidate(true); }));