[英]Prevent hanging in windows forms
我有問題 因此,我構建了一個應用程序,該應用程序以圖表和datagridview的形式顯示數據。 他們都反應靈敏。 這意味着它們將重新縮放並隨數據一起移動。 我猜這需要一些計算能力。
同時,我有計時器,使它們全部以f = 4Hz周期性運行。
現在:當我運行該應用程序並打開定期讀數時,該應用程序在調整大小時會掛起。 我該如何預防呢?
我已經嘗試使用backgroundworker,但是在訪問在“其他線程”中聲明(並使用)的datagridview和chart時,就會出現問題(如VS所說)
所以..我該如何預防呢? 也許我應該以其他方式利用背景工作者?
我對背景工作人員的嘗試:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Control.CheckForIllegalCrossThreadCalls = false;
if (!GetConnectionStatus())
{
stop_ticking();
if (MessageBox.Show("Device not connected", "Connection status", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) == DialogResult.Retry)
messaging();
else
return;
}
// TEMP READ
Read_temp(tlist);
float[] t = new float[3];
float[] r = new float[3];
float[] av = new float[1];
float[] st = new float[1];
// TEMP IMPORT
tlist.Give_current_temp(t, r, av, st);
string time_stamp = tlist.Give_current_time();
rows_nr++;
// ADDING TO GRID
dataGridView1.Invoke(new Action(() => { dataGridView1.Rows.Add(new object[] { rows_nr, time_stamp, av[0], st[0], (t[0]).ToString(), (r[0]).ToString(), (t[1]).ToString(), (r[1]).ToString(), (t[2]).ToString(), (r[2]).ToString() }); }));
//dataGridView1.Rows.Add(new object[] { rows_nr, time_stamp, av[0], st[0], (t[0]).ToString(), (r[0]).ToString(), (t[1]).ToString(), (r[1]).ToString(), (t[2]).ToString(), (r[2]).ToString() });
dataGridView1.Invoke(new Action(() => { dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1; }));
//dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;
// ADDING TO CHART
for (int i = 0; i < 3; i++)
chart1.Invoke(new Action(() => { chart1.Series[series_names[i]].Points.AddXY((rows_nr), (t[i])); }));
//chart1.Series[series_names[i]].Points.AddXY((rows_nr), (t[i]));
chart1.Invoke(new Action(() => { chart1.Series["average"].Points.AddXY((rows_nr), (av[0])); }));
//chart1.Series["average"].Points.AddXY((rows_nr), (av[0]));
//chart1.Series["std1"].Points.AddXY((rows_nr), (av[0] + Math.Abs(st[0])));
//chart1.Series["std2"].Points.AddXY((rows_nr), (av[0] - Math.Abs(st[0])));
// MOVING CHART
if (chart1.Series[series_names[0]].Points.Count > nr_of_noints_graph)
{
for (int i = 0; i < 3; i++)
chart1.Series[series_names[i]].Points.RemoveAt(0);
chart1.Series["average"].Points.RemoveAt(0);
//chart1.Series["std1"].Points.RemoveAt(0);
//chart1.Series["std2"].Points.RemoveAt(0);
chart1.ChartAreas[0].AxisX.Minimum = rows_nr - (nr_of_noints_graph - 1);
chart1.ChartAreas[0].AxisX.Maximum = rows_nr;
dataGridView1.Rows.RemoveAt(0);
}
chart1.Invoke(new Action(() => { chart1.ChartAreas[0].RecalculateAxesScale(); }));
//chart1.ChartAreas[0].RecalculateAxesScale();
}
請看一下背景工作者樣本。 你做錯了。 后台工作程序DoWork不應調用UI控件,並且應在非UI線程中執行,它應執行耗時的計算並調用worker.ReportProgress()。 雖然ReportProgress方法可以訪問UI控件,但是此方法中的代碼在UI線程中執行。 在添加/刪除點時,某些圖表控件比較笨拙。 可能因為掛住而掛起。 減少更新的頻率(例如1秒1秒鍾),然后查看其是否掛起。
在Stopwatch中包裝操作,並使用System.Diagnostics.Debug.WriteLine跟蹤執行流程和操作時間。
移動圖表部件不起作用,因為它在沒有調用UI線程的情況下訪問了非ui線程中的UI元素。
如果不是背景工作者,我會這樣寫:
// MOVING CHART
chart1.Invoke(new Action(()=>
{
if (chart1.Series[series_names[0]].Points.Count > nr_of_noints_graph)
{
for (int i = 0; i < 3; i++)
chart1.Series[series_names[i]].Points.RemoveAt(0);
chart1.Series["average"].Points.RemoveAt(0);
chart1.ChartAreas[0].AxisX.Minimum = rows_nr - (nr_of_noints_graph - 1);
chart1.ChartAreas[0].AxisX.Maximum = rows_nr;
}
}
));
我也不會將每個操作都包裝在單獨的Invokes中。
關於您的問題,沒有足夠的信息來檢測出問題所在,請提供最小的可運行樣本以證明問題所在。
由於@Access拒絕狀態,您應該改善GUI和后台工作線程之間的分離。 您可以在后台線程上執行// TEMP READ
和// TEMP IMPORT
操作,並在所有數據就緒后通過.Invoke
方法調用GUI線程。 請閱讀“如何:對Windows窗體控件進行線程安全的調用”一文,以了解更多信息。
在DataGridView
添加/更新數據時,請使用.BeginUpdate
/ .EndUpdate
方法來防止控件更新,直到刷新所有數據為止。
另一種方法是使用虛擬模式 。 如果網格中有很多項目,這將特別有用。
使用后台線程時,您不得創建,更新甚至訪問任何UI元素。
您需要將檢索數據的工作(較慢的部分)與更新圖表的工作(非常快)分開。
真正歸結為這樣:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (!GetConnectionStatus())
{
stop_ticking();
return;
}
// TEMP READ
Read_temp(tlist);
float[] t = new float[3];
float[] r = new float[3];
float[] av = new float[1];
float[] st = new float[1];
// TEMP IMPORT
tlist.Give_current_temp(t, r, av, st);
string time_stamp = tlist.Give_current_time();
rows_nr++;
chart1.Invoke(new Action(() =>
{
// ADDING TO GRID
dataGridView1.Rows.Add(new object[] { rows_nr, time_stamp, av[0], st[0], (t[0]).ToString(), (r[0]).ToString(), (t[1]).ToString(), (r[1]).ToString(), (t[2]).ToString(), (r[2]).ToString() });
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;
// ADDING TO CHART
for (int i = 0; i < 3; i++)
{
chart1.Series[series_names[i]].Points.AddXY((rows_nr), (t[i]));
}
chart1.Series["average"].Points.AddXY((rows_nr), (av[0]));
// MOVING CHART
if (chart1.Series[series_names[0]].Points.Count > nr_of_noints_graph)
{
for (int i = 0; i < 3; i++)
{
chart1.Series[series_names[i]].Points.RemoveAt(0);
}
chart1.Series["average"].Points.RemoveAt(0);
chart1.ChartAreas[0].AxisX.Minimum = rows_nr - (nr_of_noints_graph - 1);
chart1.ChartAreas[0].AxisX.Maximum = rows_nr;
dataGridView1.Rows.RemoveAt(0);
}
chart1.ChartAreas[0].RecalculateAxesScale();
}));
}
如果必須顯示一個MessageBox,則還需要調用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.