【发布时间】:2008-11-03 16:13:47
【问题描述】:
我的应用有一个 DataGridView 对象和一个 MousePos 类型的列表。 MousePos 是一个自定义类,它保存鼠标 X、Y 坐标(类型为“Point”)和该位置的运行计数。我有一个线程 (System.Timers.Timer) 每秒引发一次事件,检查鼠标位置,添加和/或更新此列表上的鼠标位置计数。
我希望有一个类似的运行线程(同样,我认为 System.Timers.Timer 是一个不错的选择),它会再次每秒引发一次事件以自动 Refresh() DataGridView,以便用户可以看到屏幕上的数据更新。 (就像 TaskManager 一样。)
不幸的是,调用 DataGridView.Refresh() 方法会导致 VS2005 停止执行并注意到我遇到了跨线程情况。
如果我理解正确,我现在有 3 个线程:
- 主 UI 线程
- MousePos 列表线程(定时器)
- DataGridView 刷新线程(定时器)
为了查看是否可以 Refresh() 主线程上的 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#] 放在主语里是禁止的吧?
标签: c# .net multithreading datagridview delegates