获取错误使用Timer类时的跨线程操作

时间:2013-02-22 21:29:54

标签: c# winforms datagridview

我有一个Winform应用程序,我对它的功能感到满意。我想每15分钟从数据库中检索最新数据,并将其显示在DataGridView中。

我添加了一个Timer类。一旦经过15分钟,我就可以调用检索并显示数据的方法。我收到了错误(请参见随附的屏幕截图)。

我在这里做错了什么?

以下是我的代码:

public partial class Form1 : Form
{
    System.Timers.Timer aTimer;

    public Form1()
    {
      InitializeComponent();
      StartTimer();
    }

    private void RetrieveData()
    {

      DataTable table = new DataTable();
      table.Rows.Add(woStatus, dateReceived, dateApprovedFormatted, binNo, ppNo, woNo, daysDifference);

      dataGridViewMain.DataSource = table;
      dataGridViewMain.Sort(dataGridViewMain.Columns["Days in the shop"], ListSortDirection.Descending);
    }

    private void StartTimer()
    {
      aTimer = new System.Timers.Timer(10000); // 10secs
      aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
      RetrieveData();
      aTimer.Start();
    }

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
      aTimer.Stop();
      aTimer.Dispose();
      StartTimer();
    }
}

2 个答案:

答案 0 :(得分:7)

System.Timers.Timer重新启动随机工作线程, UI线程。因此,当代码进入RetrieveData(通过OnTimedEvent然后StartTimer)时,它就是错误的线程。您可以使用this.Invoke((MethodInvoker) delegate {...})来获取正确的线程,但是使用System.Windows.Forms.Timer组件可能更简单,因为它会自动(通过sync-context)在UI线程上触发。

答案 1 :(得分:1)

我没有看到任何屏幕截图,但如果你得到一个跨线程异常,我会怀疑它,因为你在StartTimer()方法中调用RetreiveData(),它在定时器线程上被称为 当它过去的时候。您需要确保影响UI的代码在与UI相同的线程上执行,否则您将获得这些异常。查看提供的方法InvokeRequired()和Control.Invoke(),以确保在上下文切换回UI线程后完成影响UI的方法调用。