내 응용 프로그램에는 DataGridView 개체와 MousePos 형식의 목록이 있습니다. MousePos는 마우스 X, Y 좌표 ("Point"유형) 및이 위치의 실행 횟수를 보유하는 사용자 정의 클래스입니다. 매초마다 이벤트를 발생시키고, 마우스 위치를 확인하고,이 목록에서 마우스 위치의 수를 추가 및/또는 업데이트하는 스레드 (System.Timers.Timer)가 있습니다.데이터를 안전하게 채우고 다중 스레드 응용 프로그램에서 DataGridView를 새로 고치려면 어떻게해야합니까?
사용자가 볼 수 있도록 DataGridView를 자동으로 Refresh()하는 두 번째 이벤트를 다시 발생시키는 비슷한 실행 스레드 (다시 말하면 System.Timers.Timer가 좋은 선택입니다)를 갖고 싶습니다. 화면의 데이터가 업데이트됩니다. (TaskManager와 마찬가지입니다.)
DataGridView.Refresh() 메서드를 호출하면 VS2005가 실행을 중지하고 크로스 스레딩 상황에 처해 있음을 알 수 있습니다.
내가 제대로 이해 해요, 난 지금 3 개 스레드가 :
- 기본 UI 스레드
- MousePos 목록 스레드 (타이머)
- 된 DataGridView 새로 고침 스레드 (타이머)
을 내가 주 스레드에서 DataGridView를 새로 고침() 할 수 있는지 확인하려면 DataGridView.Refresh()라는 양식에 단추를 추가했지만이 (이상하게) 아무것도 수행하지 않았습니다. DataGridView.DataSource = null로 설정하고 내 목록으로 돌아 가면 DataGrid를 새로 고칩니다.
- 가 DataGridView.DataSource 설정되어 : 그리고 실제로이 있지만 버튼을 통해 (. 어떤이 기본 스레드에서 처리됩니다)
그래서이 질문은 두 파트너 사에 설정되어있다, 일 null 및 다시 내 목록에 데이터 그리드를 새로 고칠 수있는 방법? (나에게 비효율적 인 것 같습니다 ...)
- 안전하게 멀티 스레드 환경에서 어떻게해야합니까?
다음은 다른 모든 컨트롤과 같은 메인 UI 스레드에서 그리드를 업데이트해야 내가 지금까지 작성한 코드 (C#을 /. 닷넷 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; }
}
: 다른 스레드에서 DataGridView에 전화를하려고한다면 그래서, 당신은 다음을 수행해야합니다? – Pretzel