C#은 작업자 스레드의 UI 인터페이스에서 컨트롤을 업데이트합니다.

C# 애플리케이션 개발에서는 인터페이스가 응답을 중지하지 않도록 작업자 스레드에서 UI 스레드를 분리하는 경우가 많습니다. 동시에 우리는 작업 스레드에서 UI 인터페이스의 컨트롤을 업데이트해야 합니다.
다음은 일반적으로 사용되는 몇 가지 방법을 소개합니다.
스레드 간의 작업은 유효하지 않습니다.
인터페이스에 버튼과 레이블이 있습니다.버튼을 클릭하면 스레드를 시작하여 레이블 값을 업데이트하십시오.

  1. private void button1_Click(개체 발신자, EventArgs e)
  2.         {
  3.             스레드 thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
  4.             thread1.Start("업데이트 Label");
  5.         }
  6.         개인 무효 UpdateLabel(개체 str)
  7.         {
  8.             this.label1.Text = str.ToString();
  9.         }
코드 복사

실행 후 프로그램은 ""label1"을 생성하지 않은 스레드에서 액세스하는 크로스 스레드 작업이 유효하지 않습니다."라는 오류를 보고합니다.


이는 .NET이 스레드 간 컨트롤 호출을 금지하기 때문입니다. 그렇지 않으면 누구나 컨트롤을 조작할 수 있으므로 결국 오류가 발생할 수 있습니다.   

다음은 여러 스레드에서 컨트롤을 호출하는 몇 가지 방법을 소개합니다.

첫 번째 방법: 컴파일러가 크로스 스레드 액세스를 확인하지 못하게 합니다. 이것은 가장 간단한 방법으로 스레드 간의 충돌을 확인하지 않고 각 스레드가 엉망이 되도록 하는 것과 같습니다. 마지막으로, Label1 컨트롤의 값이 무엇인지 예측할 수 없음( 이 방법은 권장하지 않음 )

  1. 공개 Form1()
  2.         {
  3.             InitializeComponent();
  4.             // 이 줄을 추가
  5.             Control.CheckForIllegalCrossThreadCalls = 거짓;
  6.         }
코드 복사


두 번째 방법: 위임 및 호출을 사용하여 다른 스레드에서 컨트롤을 호출하여 컨트롤의 호출 메서드를 호출한 다음 예를 들어 컨트롤을 제어할 수 있습니다.

  1. private void button2_Click(개체 발신자, EventArgs e)
  2.         {
  3.             스레드 thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
  4.             thread1.Start("업데이트 Label");
  5.         }
  6.         개인 무효 UpdateLabel2(개체 str)
  7.         {
  8.             if (label2.InvokeRequired)
  9.             {
  10.                 // 컨트롤의 InvokeRequired 속성 값이 true이면 컨트롤을 생성하는 스레드가 아닌 다른 스레드에서 액세스를 원한다는 의미입니다.
  11.                 Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
  12.                 // 또는
  13.                 // Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
  14.                 this.label2.Invoke(actionDelegate, str);
  15.             }
  16.             또 다른
  17.             {
  18.                 this.label2.Text = str.ToString();
  19.             }
  20.         }
코드 복사


세 번째 방법: 대리자와 BeginInvoke를 사용하여 다른 스레드에서 컨트롤을 제어합니다. 위의 this.label2.Invoke(actionDelegate, str);에서 Invoke를 BeginInvoke 메서드로 변경하면 됩니다.
Invoke 메서드와 BeginInvoke 메서드의 차이점은 다음과 같습니다. 해당
Invoke 메서드는 동기식이며, 작업자 스레드가 완료될 때까지 대기하고,
BeginInvoke 메서드는 비동기식이며, 다른 스레드를 시작하여 작업자 스레드를 완료합니다.

네 번째 방법: BackgroundWorker 구성 요소 사용(이 방법 사용 권장) BackgroundWorker는 프로그래머가 별도의 스레드에서 일부 작업을 수행할 수 있도록 하는 다중 스레드 작업을 위해 .NET 컨트롤에서 실행하는 데 사용됩니다. 다운로드 및 데이터베이스 트랜잭션과 같이 시간이 많이 걸리는 작업. 사용하기 쉬운
 

  1. private void button4_Click(개체 발신자, EventArgs e)
  2.         {
  3.             (BackgroundWorker bw = new BackgroundWorker()) 사용
  4.             {
  5.                 bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
  6.                 bw.DoWork += new DoWorkEventHandler(bw_DoWork);
  7.                 bw.RunWorkerAsync("탱크");
  8.             }         
  9.         }
  10.         void bw_DoWork(개체 발신자, DoWorkEventArgs e)
  11.         {      
  12.             // 이것은 다른 스레드에서 수행되는 백그라운드 스레드입니다.
  13.             // 실제로 작업을 수행하는 작업자 스레드는 다음과 같습니다.
  14.             // 여기에서 시간이 많이 걸리고 복잡한 작업을 수행할 수 있습니다.
  15.             스레드.슬립(5000);
  16.             e.Result = e.Argument + "작업자 스레드 완료";
  17.         }
  18.         무효 bw_RunWorkerCompleted(개체 발신자, RunWorkerCompletedEventArgs e)
  19.         {
  20.             // 이때 백그라운드 쓰레드가 완료되어 메인 쓰레드로 반환되었으므로 UI컨트롤을 바로 사용할 수 있다.
  21.             this.label4.Text = e.Result.ToString();
  22.         }

 

Supongo que te gusta

Origin blog.csdn.net/u014090257/article/details/125651551
Recomendado
Clasificación