我尝试使用计时器每秒连接并向DatagridView1显示数据库。我是C#的新手,所以我对线程系统感到困惑。我尝试从计时器调用munculkantabel()并始终返回跨线程操作无效:从除创建它的线程以外的线程访问控件。那么如何修复这段代码?
public void buattimer()
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(backgroundWorker1_DoWork);
aTimer.Interval = 1000;
aTimer.Enabled = true;
}
public void backgroundWorker1_DoWork(object source, ElapsedEventArgs e)
{
Thread thh = new Thread(munculkantabel);
thh.Start();
}
string constring = "datasource=localhost;port=3306;username=root;password=;convert zero datetime=True";
public void munculkantabel()
{
MySqlConnection conDataBase = new MySqlConnection(constring);
MySqlCommand cmdDataBase = new MySqlCommand(" select * from konsentrasi.okedeh ;", conDataBase);
try
{
MySqlDataAdapter sda = new MySqlDataAdapter();
sda.SelectCommand = cmdDataBase;
DataTable dbdataset = new DataTable();
sda.Fill(dbdataset);
BindingSource bSource = new BindingSource();
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
答案 0 :(得分:0)
GUI组件与运行GUI消息泵的线程绑定。
从任何其他线程直接访问是未定义行为的道路(如果您运气好,其他一切......,某些事情可能会起作用。)
相反,从工作线程(例如,响应于计时器事件)需要使用GUI的BeginInvoke
(这是前一段的一个例外)方法控制在GUI线程上执行任何操作。
在您的代码中,替换
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
使用:
dataGridView1.BeginInvoke(() => {
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
});
当然,任何依赖于对数据网格的更改的代码也可以类似地在GUI线程上运行,以便已知上述代码已经完成。在您的情况下,您不会直接受此影响,因为您没有清理数据库连接等。(答案:清除GUI线程上的连接等,或至少在GUI线程之后启动的任务中)上面的代码)。
另请注意,BeginInvoke
也是&#34的例外情况;如果您已调用BeginABC
,则必须致电EndABC
以执行任何清理工作"规则:在这种情况下,不需要EndInvoke
(并且记录如此)。
答案 1 :(得分:0)