使用安全Thead或后台工作者的C#麻烦

时间:2014-10-09 19:43:47

标签: c# thread-safety

相当令人沮丧,因为这似乎有很好的记录和事实,我之前完成了这一事实,但不能重复同样的成功。对不起,我会尝试清楚地说明这一点。

Visual Studio,C#表单,一个主表单包含文本字段以及其他小部件。

我们有一个概念,即我们正在“运行”,因此收集数据。

目前,我启动了一秒计时器,以便我可以将模拟数据更新到某些字段中。最终,一秒计时器将获取更快速的数据,并且每秒仅更新一次到屏幕,这就是对应用程序的请求,我们现在以我们收到的速率更新,这有点超过70赫兹,他们不想要就这样。此外,还将计算一些其他统计数据,这些数据应该是字段更新。因此很简单我只想生成随机数据并以1 Hz的速率更新这些字段。然后从那时开始扩展。

定时器的定义和管理:(这都在同一类MainScreen中)

System.Timers.Timer oneSecondTimer;
public UInt32 run_time = 0;
public int motion = 5;

private void InitializeTimers()
{
    this.oneSecondTimer = new System.Timers.Timer(1000);
    this.oneSecondTimer.Elapsed += new System.Timers.ElapsedEventHandler(oneSecondTimer_elapsed);
}

public void start_one_second_timer()
{
    run_time = 0;
    oneSecondTimer.Enabled = true;
}

public void stop_one_second_timer()
{
    oneSecondTimer.Enabled = false;
    run_time = 0;
}

Random mot = new Random();

private void oneSecondTimer_elapsed(object source, System.Timers.ElapsedEventArgs e)
{
    run_time++;
    motion = mot.Next(1, 10);

    this.oneSecondThread = new Thread(new ThreadStart(this.UpdateTextFields));

    this.oneSecondThread.Start();
}

private void UpdateTextFields()
{
    this.motionDisplay.Text = this.motion.ToString();
}

motionDisplay只是我主要表单中的一个文本框。我得到了无效操作异常,指向我如何进行线程安全调用的帮助。我也试过backgroundworker并得到相同的结果。详细信息是可以从创建它的线程以外的线程访问motionDisplay。

所以寻找一些关于我的错误在哪里的建议。

最诚挚的问候。我继续对此进行迭代,如果找到解决方案,我会更新。

3 个答案:

答案 0 :(得分:1)

试试这个

private void UpdateTextFields()
{
    this.BeginInvoke(new EventHandler((s,e)=>{
        this.motionDisplay.Text = this.motion.ToString();
    }));
}

这将正确地回复主线程。

WinForm开发的一点是所有控件都不是线程安全的。即使从另一个线程获取诸如.Text之类的属性也可能导致这些类型的错误发生。让它更令人沮丧的是,有时它会在运行时工作,你不会得到例外,有时你也会。

答案 1 :(得分:1)

使用System.Forms.Timer而不是System.Timers.Timer。它将在UI线程中触发它已经过去的事件。

不要创建新线程来更新UI;只需在已过时的事件处理程序中进行更新。

答案 2 :(得分:1)

我就是这样做的:

private delegate void UpdateMotionDisplayCallback(string text);
private void UpdateMotionDisplay(string text) {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.motionDisplay.InvokeRequired) {
            UpdateMotionDisplayCallback d = new UpdateMotionDisplayCallback(UpdateMotionDisplay);
            this.Invoke(d, new object[] { text });
        } else {
            this.motionDisplay.Text = text;
        }
    }

如果要更新motionDisplay中的文本,请调用:

UpdateMotionDisplay(this.motion.ToString())