진행중인 Winforms 컨트롤 (DataGridView)을 업데이트해야하는 멀티 스레드 응용 프로그램에서 작업하고 있습니다. 나는 다음 DGV가 UI 스레드에서 생성 된 이후, 그것은 .Invoke()
'라 할 필요가 있음을 깨달았다Lock (Control) 대신 Control.Invoke() 사용
if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
while (DGV.Columns.Count < DesiredColumnCount)
{
DGV.Columns.Add(newColumn);
}
}
: 같은 공유 리소스에 다중 접속을 방지하기 위해, 나는 다음과 같은 잠금 구조로 시작 . 그러면 코드가 다음과 같이 변경됩니다.
if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
DGV.Invoke(new MethodInvoker(() =>
{
while (DGV.Columns.Count < DesiredColumnCount)
{
DGV.Columns.Add(newColumn);
}
}
}
내 질문은 : 중복이 아닙니까? lock
은 단독 스레드가 DGV
에 액세스 할 때까지 작업자 스레드를 차단하고 Invoke()
은 UI 스레드가 호출 요청을 받아서 코드를 실행할 때까지 작업자 스레드를 차단합니다. Invoke()
만 사용하면 안 될까요?
(즉. 주요 질문은 위의 코드에서 다른 멀티 스레딩 죄가 있다면 물론, 의견을주세요) 그것은 조금 중복
"작업자 스레드"에 대해 무엇을 사용하고 있습니까? –
UI 스레드를 절대로 차단해서는 안됩니다. Control 및 Invoke뿐만 아니라 잠금도 마찬가지입니다. 잠금을 제거하고 Invoke to BeginInvoke를 변경해야합니다. –
@ PeterRitchie 정확하게 스레드를 시작한 것을 기억하지 못합니다. 아마도 새로운 스레드(). Start() 또는 System.Threading.Timer.Elapsed입니다. 이 코드는 UI 스레드를 차단하지 않았으므로 작업자를 차단했을 것입니다. BeginInvoke는 호출자를 차단하지 않으므로 Invoke를 맹목적으로 대체 할 수 없습니다. 호출 순서를 잘못 지정하여 서로의 순서가 잘못되어 실행되지 않도록해야합니다. 이는 작업자 스레드를 차단하는 데 소요되는 시간을 줄여 성능을 향상시킬 수 있지만 지금까지는 오래된 프로젝트입니다. – Nathan