2014-12-17 4 views
0

나는 별도의 스레드가 winforms 응용 프로그램에서 GUI를 변경하기 위해 메서드를 호출해야한다는 것을 이해했다고 생각했습니다. 그러나, 나는 비동기 적으로 콤보 박스를 채우는 방법을 썼다. 그리고 그것은 이야기에 더 많은 것이 있음을 보여준다.어떤 조건에서 메소드를 호출해야합니까?

private List<string> ids = new List<string>(); 
private BindingSource bindingSource = new BindingSource(); 
//... 
cboIds.DataSource = bindingSource; 

private void GetAvailableIds() 
{ 
    Task idTask = new Task(
     () => 
     { 
      bindingSource.Add("Searching..."); //This always updates the UI 
                //without invoking 

      if (cboIds.InvokeRequired)  
      { 
       Invoke((MethodInvoker)delegate 
       {        //This sometimes updates the UI without 
        cboIds.Enabled = false;  //invoking, but sometimes fails, so I              
       });        //added the check 
      } 
      else 
       cboIds.Enabled = false; 

      List<string> temp = GetUpcomingIds(); 

      Invoke((MethodInvoker)delegate 
      { 
       cboIds.Enabled = true; 
       bindingSource.Clear(); 
       foreach (string str in temp) 
        bindingSource.Add(str); //This never works without invoking. 
      });        //Why, if the same operation above 
     });         //always works without invoking? 
    idTask.Start(); 
} 

가 왜 BindingSource에 대한 초기 추가는 때때로 호출을 필요로 false로 combobox.enabled 설정, 인보을 필요로하지 않습니다 그 것이다 : 여기

은 생략 회사 정보와 관련 코드입니다 , BindingSource의 마지막 추가는 항상 호출되어야합니다. 그들은 모두 같은 스레드에 있다면, 그들은 같은 행동을해서는 안됩니다? 나는 그들이 모두 같은 스레드에 있다는 나의 가정에서 틀렸는가?

+0

winform 컨트롤에 액세스 할 때 호출해야하는 컨트롤을 만들지 못한 스레드 양식을 만듭니다. – dotctor

+1

'Task' <>'Thread'. –

+0

스레드가 아닌 작업을 사용하므로 여기에서 보는 문제는 무엇입니까? – charlieparker

답변

0

지금까지 Invoke()이 필요한, 또는 비동기 해당 BeginInvoke()이 필요한 경우 때와 : 당신은 당신이 개체를 소유 한 스레드가 아닌 다른 스레드의 모든 Control 클래스 객체와 상호 작용을 할 때 사용합니다. Control 개체는 생성 된 스레드가 소유합니다 (이 소유권은 관리되는 Control 개체가 나타내는 원시 데이터 구조에 대한 기본 스레드 선호도 때문입니다).

제공된 코드 예제와 달리 BindingSource 개체를 일부 컨트롤에 첨부 한 경우 바인딩 된 데이터를 수정하는 해당 개체의 멤버를 실행할 때 Invoke()을 사용해야합니다. 해당 멤버를 실행하는 경우 BindingSource가 바인드되고있는 컨트롤을 소유하고있는 thread 이외의 thread 이는 BindingSource 개체가 컨트롤에서 처리하는 이벤트를 발생시키기 때문입니다. 그 상호 작용은 컨트롤을 소유 한 스레드에서 발생해야하며이를 수행하는 유일한 방법은 BindingSource의 업데이트 실행을 Invoke()이있는 소유 스레드로 이동하는 것입니다. 방법.

개체가 컨트롤에 연결되어 있지 않고 나중에 첨부 된 경우 컨트롤에 연결된 시점까지 객체에 대한 수정을 수행 할 때 Invoke()이 필요하지 않습니다. . 그것은 당신의 코드 예제가 완료되지 않은 것을 어떻게 당신이 실제로 할 경우 컨트롤에 만든 bindingSource 인스턴스를 연결하지만, 나중에 Invoke()을 필요로하는 이유 Add() 방법에 대한 첫 번째 호출 후, 그 설명 할 수 있지만하지 않는 초기 호출은 Add()입니다.

이제 모든 것을 염두에두고 & hellip;

DataSource 바인딩의 경우 컨트롤을 직접 업데이트하려고했을 때처럼 을 BindingSource으로 수정하지 않아도됩니다. 그 대신 바인딩은 제어가 가능한 시간 (예 : BindingSource)이 컨트롤을 소유하는 스레드에서 업데이트 될 때까지 컨트롤의 업데이트를 지연시킵니다.

은 코드 예제에서는 컨트롤이있는 당신이 바로 그 후 소유하는 스레드로 돌아가 않기 때문에이 통지하지 않습니다, 첫 번째 Add() 메서드를 호출 할 때 즉시 업데이트되지 동안 것을 의미한다 컨트롤을 업데이트 할 수있는 시간. 나는. 기술적으로 당신은 첫 번째 업데이트에 대한 Invoke()를 사용하는 필요성을 ,하지만 모두가 그냥 "잘못된 방향으로" "올바른 방법"그 일을하고 그 일의 차이에 주목하지 않는 것이 너무 빨리 발생합니다.

+0

BindingSource 객체는 호출되기 전에 cboIds에 연결됩니다. 이를 보여주기 위해 샘플을 업데이트하겠습니다. – charlieparker

+0

아, 알았어 ... 나는 내 대답을 맞게 업데이트 할 것이다. –

관련 문제