我的應用程序有一個DataGridView對象和一個MousePos類型的列表。 MousePos是一個自定義類,它包含鼠標X,Y座標(類型爲「Point」)和該位置的運行計數。我有一個線程(System.Timers.Timer),每秒產生一次事件,檢查鼠標位置,添加和/或更新此列表中鼠標位置的計數。如何在多線程應用程序中安全地填充數據並刷新()DataGridView?
我想有一個類似的運行線程(同樣,我認爲System.Timers.Timer是一個不錯的選擇),它會再次引發一次事件,自動刷新()DataGridView,以便用戶可以看到屏幕上的數據更新。 (如任務管理器一樣。)
不幸的是,調用VS2005的DataGridView.Refresh()方法將導致停止執行,並指出,我碰到一個跨線程情況。
如果我理解正確的話,我現在有3個線程:
- 主UI線程
- mousePos結構列表線程(計時器)
- 的DataGridView刷新線程(定時器)
爲了查看我是否可以在主線程上刷新DataGridView,我添加了一個名爲DataGridView.Refresh()的表單的按鈕,但是這個(奇怪的是)沒有做任何事情。我發現一個話題似乎表明,如果我設置DataGridView.DataSource = null並返回到我的列表,它會刷新數據網格。事實上這個工作,但只能通按鈕(它獲取的主線程處理。)
所以這個問題已經變成了兩個舞伴:
- 是設置DataGridView.DataSource到null並返回到我的List一個可接受的方式刷新數據網格? (這似乎效率不高,我...)
- 我如何安全地做到這一點在多線程環境中?
這裏是我到目前爲止已經編寫的代碼(C#/。NET 2.0)
public partial class Form1 : Form
{
private static List<MousePos> mousePositionList = new List<MousePos>();
private static System.Timers.Timer mouseCheck = new System.Timers.Timer(1000);
private static System.Timers.Timer refreshWindow = new System.Timers.Timer(1000);
public Form1()
{
InitializeComponent();
mousePositionList.Add(new MousePos()); // ANSWER! Must have at least 1 entry before binding to DataSource
dataGridView1.DataSource = mousePositionList;
mouseCheck.Elapsed += new System.Timers.ElapsedEventHandler(mouseCheck_Elapsed);
mouseCheck.Start();
refreshWindow.Elapsed += new System.Timers.ElapsedEventHandler(refreshWindow_Elapsed);
refreshWindow.Start();
}
public void mouseCheck_Elapsed(object source, EventArgs e)
{
Point mPnt = Control.MousePosition;
MousePos mPos = mousePositionList.Find(ByPoint(mPnt));
if (mPos == null) { mousePositionList.Add(new MousePos(mPnt)); }
else { mPos.Count++; }
}
public void refreshWindow_Elapsed(object source, EventArgs e)
{
//dataGridView1.DataSource = null; // Old way
//dataGridView1.DataSource = mousePositionList; // Old way
dataGridView1.Invalidate(); // <= ANSWER!!
}
private static Predicate<MousePos> ByPoint(Point pnt)
{
return delegate(MousePos mPos) { return (mPos.Pnt == pnt); };
}
}
public class MousePos
{
private Point position = new Point();
private int count = 1;
public Point Pnt { get { return position; } }
public int X { get { return position.X; } set { position.X = value; } }
public int Y { get { return position.Y; } set { position.Y = value; } }
public int Count { get { return count; } set { count = value; } }
public MousePos() { }
public MousePos(Point mouse) { position = mouse; }
}
我猜把[C#]在主題是禁止的,是吧? – Pretzel 2008-11-03 19:05:13