저는 백그라운드 스레드에서 메인 인터페이스를 업데이트하는 방법에 관한 입문 기사를 많이 읽었는데, 대부분 Control.Invoke와 Control.BeginInvoke를 사용합니다. 이것들은 좋은 해결책이지만, 두 가지 문제가 있습니다:
1. System.Windows.Forms를 참조한 후 System.Windows.Forms를 사용해야 합니다
2. 코드 구조가 비교적 복잡합니다. (사실 이것도 #1 때문이기도 합니다)
마이크로소프트는 더 세련된 솔루션인 System.Threading을 제공합니다. SynchronizationContext. 보시다시피, Namesapce System.Windows.Forms에는 없기 때문에 BusinessLaryer, Controler, 심지어 모듈에서도 정당하게 사용할 수 있습니다.
그리고 매우 편리하게 사용하며, 다음 두 가지 방법에만 집중하면 됩니다:
1. 전송: 인터페이스 업데이트 요청을 메인 스레드에 보내며, 현재 스레드가 돌아올 때까지 차단합니다.
2. 게시: 현재 스레드를 차단하지 않고 메인 스레드에 인터페이스 업데이트 요청을 보냅니다.
사실 모두 같은 방식인데, 전송은 동기식이고 post는 비동기식입니다
Form1 form = new Form1() 이전에는, SynchronizationContext 객체가 비어 있었고, Form1 폼이 인스턴스화될 때 SynchronizationContext 객체가 이 스레드에 추가되었습니다. 그래서 답은 컨트롤 객체가 생성될 때, SynchronizationContext 객체도 생성되어 스레드에 부착됩니다. 모두 InitializeComponent() 형태를 사용할 때; 이 작업이 완료되면 NULL이 아닌 객체를 얻을 수 있습니다
마지막으로, SynchronizationContext의 Sendt()와 Post() 방법의 차이점:
Send()는 현재 스레드에서 대리자를 호출하는 것(동기식 호출)으로 구현됩니다. 즉, UI 스레드는 서브스레드에서 직접 호출되어 실행되며, UI 스레드 실행이 완료된 후에도 서브스레드는 계속 실행됩니다.
Post()는 스레드 풀에서 위임자를 호출하여 구현됩니다(비동기 호출). 이는 서브스레드가 스레드 풀에서 스레드를 찾아 UI 스레드를 튜닝하고, 서브스레드가 UI 스레드가 완료될 때까지 기다리지 않고 직접 자신의 코드를 실행하기 때문입니다. 테스트 코드:
결과:
UI 메인 스레드: 1 스레드: 5 동기화 컨텍스트:1
요약:UI 스레드의 SynchronizationContext 객체는 메인 스레드에서 호출되었든 스레드 내에서 호출되었든, 메인 스레드에서 실행되기 때문에, 시간이 많이 소요되는 코드가 많으면 UI 인터페이스가 멈추거나 죽음을 가장할 수 있습니다!
사실은UI 스레드는 SynchronizationContext 클래스가 아니라 WindowsFormsSynchronizationContext를 사용합니다이 동동.
System.Threading.SynchronizationContext 소스 코드:
WindowsFormsSynchronizationContext 소스 코드:
|