Windows Forms에서 UI 스레드인지 여부를 결정합니다. Control.Invoke는 무엇을하고 InvokeRequired는 무엇을 어떻게 조사하고 있습니까?
6672 단어 .NETFrameworkWin32API
소개
Windows Forms 응용 프로그램 등에서 멀티스레드 응용 프로그램을 만들 때는 폼이나 컨트롤에 작성한 스레드에서 액세스해야 합니다.
제목 애플리케이션
이러한 느낌의 폼으로, 1초마다 현재 시각을 갱신 표시하는 어플리케이션을 작성해 보겠습니다.
폼을 작성한 thread로부터 태스크를 생성(=다른 thread)해 갱신 표시를 시키는 구조의, 이런 느낌의 코드를 실행시키면(자), 태스크내에서 라벨 컨트롤 (label1)의 텍스트를 갱신하려고 했을 때 「 InvalidOperationException : 유효하지 않은 스레드 간의 조작 : 컨트롤이 작성된 스레드 이외의 스레드가 컨트롤 'label1'에 액세스했습니다."예외가 발생합니다.
Form1.csusing System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Run(() =>
{
for(; ; )
{
label1.Text = DateTime.Now.ToString("HH:mm:ss"); // <- 例外発生
System.Threading.Thread.Sleep(1000);
}
});
}
}
}
독점적으로 작업용으로 만든 스레드(작업자 스레드)에서 폼이나 컨트롤 등이 속하는 스레드(UI 스레드)로 처리를 하려면 Control.Invoke 메서드를 사용해야 하며 레이블 컨트롤의 Text 속성에 쓰는 처리 의 코드를 다음과 같이 변경하면 잘 동작합니다.
Task.Run(() =>
{
for (; ; )
{
Invoke((MethodInvoker)delegate
{
label1.Text = DateTime.Now.ToString("HH:mm:ss");
});
System.Threading.Thread.Sleep(1000);
}
});
과연, 이 Invoke 메소드는, 무엇을 하고 있는 것일까요?
Invoke 메서드 처리
.NET Framework (4.7.2) 소스 코드를 읽어 보았습니다. 꽤 대략적으로 쓰면 다음을하고 있습니다.
이러한 느낌의 폼으로, 1초마다 현재 시각을 갱신 표시하는 어플리케이션을 작성해 보겠습니다.
폼을 작성한 thread로부터 태스크를 생성(=다른 thread)해 갱신 표시를 시키는 구조의, 이런 느낌의 코드를 실행시키면(자), 태스크내에서 라벨 컨트롤 (label1)의 텍스트를 갱신하려고 했을 때 「 InvalidOperationException : 유효하지 않은 스레드 간의 조작 : 컨트롤이 작성된 스레드 이외의 스레드가 컨트롤 'label1'에 액세스했습니다."예외가 발생합니다.
Form1.cs
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Run(() =>
{
for(; ; )
{
label1.Text = DateTime.Now.ToString("HH:mm:ss"); // <- 例外発生
System.Threading.Thread.Sleep(1000);
}
});
}
}
}
독점적으로 작업용으로 만든 스레드(작업자 스레드)에서 폼이나 컨트롤 등이 속하는 스레드(UI 스레드)로 처리를 하려면 Control.Invoke 메서드를 사용해야 하며 레이블 컨트롤의 Text 속성에 쓰는 처리 의 코드를 다음과 같이 변경하면 잘 동작합니다.
Task.Run(() =>
{
for (; ; )
{
Invoke((MethodInvoker)delegate
{
label1.Text = DateTime.Now.ToString("HH:mm:ss");
});
System.Threading.Thread.Sleep(1000);
}
});
과연, 이 Invoke 메소드는, 무엇을 하고 있는 것일까요?
Invoke 메서드 처리
.NET Framework (4.7.2) 소스 코드를 읽어 보았습니다. 꽤 대략적으로 쓰면 다음을하고 있습니다.
POST 된 대상 UI 스레드의 메시지 펌프 (WndProc)에서 스레드 콜백에 대한 창 메시지를 받으면 큐를 검색하고 메서드를 호출합니다 (큐가 비어있을 때까지 반복).
덧붙여서 Control.InvokeRequired 프로퍼티은, 상기 중 1. 의 처리를 실시해, 같은 thread이면 false, 다른 경우는 true 를 돌려줍니다.
결론
조금 흥미가 있었으므로, 조사해 보았습니다. .NET Framework 소스 코드를 쉽게 살펴볼 수 있는 Visual Studio 확장 프로그램인 Ref12은 항상 신세를 지고 있습니다.
Reference
이 문제에 관하여(Windows Forms에서 UI 스레드인지 여부를 결정합니다. Control.Invoke는 무엇을하고 InvokeRequired는 무엇을 어떻게 조사하고 있습니까?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/otagaisama-1/items/b101228f183249cc65b5
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Windows Forms에서 UI 스레드인지 여부를 결정합니다. Control.Invoke는 무엇을하고 InvokeRequired는 무엇을 어떻게 조사하고 있습니까?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/otagaisama-1/items/b101228f183249cc65b5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)