C# Language
비동기 대기 상태의 동기화 컨텍스트
수색…
async / await 키워드에 대한 의사 코드
간단한 비동기 메서드를 생각해보십시오.
async Task Foo()
{
Bar();
await Baz();
Qux();
}
간단히 말해서이 코드는 실제로 다음을 의미한다고 말할 수 있습니다.
Task Foo()
{
Bar();
Task t = Baz();
var context = SynchronizationContext.Current;
t.ContinueWith(task) =>
{
if (context == null)
Qux();
else
context.Post((obj) => Qux(), null);
}, TaskScheduler.Current);
return t;
}
async
/ await
키워드는 현재 동기화 컨텍스트가있는 경우이를 사용합니다. 즉, UI, 웹 및 콘솔 응용 프로그램에서 올바르게 작동하는 라이브러리 코드를 작성할 수 있습니다.
출처 기사 .
동기화 컨텍스트 비활성화
동기화 컨텍스트를 비활성화하려면 ConfigureAwait
메서드를 호출해야합니다.
async Task() Foo()
{
await Task.Run(() => Console.WriteLine("Test"));
}
. . .
Foo().ConfigureAwait(false);
ConfigureAwait는 기본 SynchronizationContext 캡처 동작을 피할 수있는 방법을 제공합니다. flowContext 매개 변수에 false를 전달하면 SynchronizationContext가 대기 후 실행을 다시 시작하는 데 사용되지 않습니다.
SynchronizationContext에 관한 모든 것부터 인용 하자 .
왜 SynchronizationContext가 중요한가?
다음 예제를 고려하십시오.
private void button1_Click(object sender, EventArgs e)
{
label1.Text = RunTooLong();
}
이 메서드는 RunTooLong
이 완료 될 때까지 UI 응용 프로그램을 고정 RunTooLong
. 응용 프로그램이 응답하지 않습니다.
비동기 적으로 내부 코드를 실행할 수 있습니다.
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() => label1.Text = RunTooLong());
}
그러나 내부 본문은 UI가 아닌 스레드에서 실행될 수 있으며 UI 속성을 직접 변경해서는 안되기 때문에이 코드는 실행 되지 않습니다 .
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
var label1Text = RunTooLong();
if (label1.InvokeRequired)
lable1.BeginInvoke((Action) delegate() { label1.Text = label1Text; });
else
label1.Text = label1Text;
});
}
이제이 패턴을 항상 사용하는 것을 잊지 마십시오. 또는 SynchronizationContext.Post
를 사용해보십시오.
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() =>
{
var label1Text = RunTooLong();
SynchronizationContext.Current.Post((obj) =>
{
label1.Text = label1 Text);
}, null);
});
}
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow