개인 기록용 포스트입니다, 잘못된 내용이 있을 수 있습니다.
Akka .NET의 SynchronizedDispatcher를 공부하던 중 해당 기능이 내부적으로 SynchronizationContext를 사용하고 있다고 해서 자세히 찾아보게 되었다.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
// Simulating a UI context capture
var synchronizationContext = SynchronizationContext.Current;
// UI triggers an asynchronous operation
ButtonClickHandler(synchronizationContext);
Console.WriteLine("Main thread continues to do other work while waiting for the async operation...");
Console.ReadLine();
}
static async Task ButtonClickHandler(SynchronizationContext synchronizationContext)
{
// Simulating an asynchronous operation like fetching data from a web service
await Task.Run(async () =>
{
// Simulating time-consuming operation
await Task.Delay(2000);
// Once the work is done, post a callback to the captured context
synchronizationContext.Post(_ =>
{
// This code executes back in the UI context
Console.WriteLine("Async operation completed! Update UI here.");
}, null);
});
}
}
SynchronizationContext는 비동기 함수에서, 어떤 특정 시점에서의 Context를 Capture했다가 나중에 다시 그 Capture한 Context에서 다른 작업을 수행할 수 있게 하기 위해 사용된다.
일반적으로 UI에서 처리 시간이 긴 행위(네트워크 IO 등)를 비동기적으로 처리할 때, UI Freezing을 막기 위해 사용한다.
즉 주로 Async한 함수 처리 관리에 사용된다고 생각하면 된다.
스레드의 Context switching과는 다르다
Capturing Context: When you capture a SynchronizationContext (often done via SynchronizationContext.Current), it captures the context of the current execution environment. For example, in a UI application, it might capture the UI context (UI thread).
Post Method: The SynchronizationContext.Post() method is used to queue a delegate (a piece of code) for asynchronous execution within the captured context. This delegate will be executed within that specific context at some point in the future.
Context Execution Mechanism: The captured context might have its own execution mechanism, such as a message loop in a UI thread. When the context processes its execution queue, it will execute the queued delegate in that context.
Asynchronous Execution: Asynchronous execution within the context managed by SynchronizationContext doesn't perform manual context switching per se. Instead, it leverages the context's existing mechanisms to execute code asynchronously within that environment.
Thread Affinity: In certain contexts like UI frameworks, SynchronizationContext helps maintain thread affinity by ensuring that asynchronous callbacks or operations happen on the correct thread. This avoids cross-threading issues and maintains consistency within that context.
In summary, SynchronizationContext doesn't manually perform low-level context switching between threads. Instead, it manages the context of asynchronous operations, ensuring that code executes within the captured context using the context's existing execution mechanisms. It's more about controlling where asynchronous code executes rather than performing manual context switching between threads.
위 코드를 보면 SynchronizationContext.Current로 해당 시점에서의 Context를 Capture하고 있다.
Capture하면 추후 해당 Context에 대해 무언가를 실행하기 위한 정보들을 저장하는데, 정확히 어떤 값이 저장되는지는 CLR이 그때그때 상황에 맞게 결정하는데, UI Context, Thread pool Context 등 상황에 따라 정보가 달라진다.
(Context란, 스레드 Context switching에서의 context와 유사한 개념으로 이해하면 되는데, 즉 어떤 실행 시점에 대한 정보라고 이해하면 된다.)
다시 코드를 살펴보면, Async한 태스크를 처리할 때 그 Context 정보를 전달하고, 태스크가 끝났을 때 전달한 Context에 .Post()로 delegate를 넘겨주는 것으로 앞에서 Capture한 시점의 context에 대해서 그 delegate를 async하게 호출해준다.
이때 .Post()는 콜백을 단지 해당 Context 환경의 큐에 전달하는 과정으로, 콜백을 바로 호출하는 행위가 아니다. 즉 위 예시 코드에서 .Post 시 delegate는 바로 실행되는 게 아니라 메인 함수 스레드의 실행 큐에 추가되고 추후 async하게 실행된다.
(실행 큐의 관리주체는 CLR이다.)
참고:
https://arong.info/List/ContentsView/1285
'lang > .NET' 카테고리의 다른 글
Akka.NET (0) | 2023.12.19 |
---|---|
Delegate (0) | 2021.05.30 |
Winform 메모 (0) | 2021.05.17 |
C#, WinForm 메모 (0) | 2021.05.17 |