Мое приложение имеет объект DataGridView и список типов MousePos. MousePos - это настраиваемый класс, который содержит координаты мыши X, Y (типа «Точка») и текущее количество этой позиции. У меня есть поток (System.Timers.Timer), который вызывает событие один раз в секунду, проверяет положение мыши, добавляет и/или обновляет подсчет позиции мыши в этом списке.Как безопасно заполнять данные и обновлять() DataGridView в многопоточном приложении?
Я бы хотел иметь подобную бегущую нить (опять же, я думаю, что System.Timers.Timer - хороший выбор), который снова поднимал бы событие раз в секунду, чтобы автоматически обновлять() DataGridView, чтобы пользователь мог видеть данные об обновлении экрана. (например, TaskManager делает.)
К сожалению, вызов метода DataGridView.Refresh() приводит к остановке выполнения VS2005 и отмечает, что я столкнулся с ситуацией с перекрестными потоками.
Если я правильно понять, у меня есть 3 темы теперь:
- Первичный поток пользовательского интерфейса
- MousePos Список нить (таймер)
- DataGridView Refresh нить (таймер)
Чтобы узнать, могу ли я обновить() DataGridView в основном потоке, я добавил кнопку в форму, называемую DataGridView.Refresh(), но это (как ни странно) ничего не делало. Я нашел тему, которая, казалось, указывала, что если я установил DataGridView.DataSource = null и вернусь в свой список, то он обновит datagrid. И действительно, это работало, но только через кнопку (которая получает обрабатывается на первичном потоке.)
Так что этот вопрос превратился в два-партер:
- ли заходящего DataGridView.DataSource к null и обратно в мой список - приемлемый способ обновления datagrid? (Мне кажется неэффективным для меня ...)
- Как я могу сделать это в многопоточной среде?
Вот код, который я написал до сих пор (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#] в теме Verboten, да? – Pretzel 2008-11-03 19:05:13