작업 순서 지정 및 재진입: 다중 스레드 환경에서 순차적 명령 관리
실제 소프트웨어 애플리케이션에서는 시나리오에 직면하는 것이 일반적입니다. 작업이 순차적으로 처리되며 실행 순서가 중요합니다. 작업이 처리 가능한 것보다 빨리 도착하고 재진입이 가능해지면 작업 순서 지정이 훨씬 더 복잡해집니다. 즉, 작업 자체 내에서 동시에 실행할 수 있다는 뜻입니다.
다음 시나리오를 고려해 보세요.
일반적으로 동기 또는 비동기 문제는 Task.Factory.StartNew 메서드를 사용하여 해결할 수 있습니다. 비동기 실행을 강제하는 TaskScheduler.FromCurrentSynchronizationContext() 매개 변수입니다. 그러나 명령 처리기가 내부적으로 동기식으로 실행되도록 설계된 경우 이 접근 방식은 이상적이지 않을 수 있습니다.
이 문제를 해결하기 위해 AsyncOp이라는 사용자 정의 클래스를 구현할 수 있습니다. AsyncOp은 작업 순서 지정 및 재진입 요구 사항을 처리합니다. 추가 기능이 포함된 AsyncOp 클래스의 업데이트 버전은 다음과 같습니다.
class AsyncOp<T> { private Task<T> _pending = Task.FromResult(default(T)); private readonly object _lock = new object(); public Task<T> CurrentTask => _pending; public Task<T> RunAsync(Func<Task<T>> handler, bool useSynchronizationContext = false) { Task<Task<T>> task = null; lock (_lock) { var pending = _pending; Task<T> wrapper = async () => { // Await the previous task T prevResult = await pending; Console.WriteLine("\nPrevious task result: " + prevResult); // Start and await the handler return await handler(); }; task = new Task<Task<T>>(wrapper); var inner = task.Unwrap(); _pending = inner; } task.RunSynchronously(useSynchronizationContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current); return inner; } public async Task HandleCancelAsync() { Task pendingCopy = null; lock (_lock) { pendingCopy = _pending; } // Cancel previous tasks as long as they are not the latest (current) task if (pendingCopy != CurrentTask && pendingCopy != null) await ((Task)pendingCopy).ContinueWith(t => t.Dispose()); } public async Task HandleRestartAsync() { Task pendingCopy = null; lock (_lock) { pendingCopy = _pending; if (pendingCopy.IsCompleted && pendingCopy != null) _pending = Task.FromResult(default(T)); } } }
이 업데이트 버전은 다음과 같은 향상된 기능을 제공합니다.
이 업데이트된 AsyncOp 클래스를 사용하면 질문에 제공된 샘플 코드를 다시 작성할 수 있습니다. 다음과 같습니다:
using System; using System.Threading.Tasks; namespace ConsoleApp { class Program { static async Task Main(string[] args) { var asyncOp = new AsyncOp<int>(); Func<int, Task<int>> handleAsync = async (arg) => { Console.WriteLine("This task arg: " + arg); // Delay the execution await Task.Delay(arg); return await Task.FromResult(arg); }; Console.WriteLine("Test #1..."); asyncOp.RunAsync(() => handleAsync(1000)); asyncOp.RunAsync(() => handleAsync(900)); asyncOp.RunAsync(() => handleAsync(800)); await asyncOp.CurrentTask; Console.WriteLine("\nPress any key to continue to test #2..."); Console.ReadLine(); asyncOp.RunAsync(() => { var handle100Task = handleAsync(100); asyncOp.RunAsync(() => handleAsync(200), true); return handle100Task; }); await asyncOp.CurrentTask; Console.WriteLine("\nPress any key to exit..."); Console.ReadKey(); } } }
이 업데이트 버전에서는 handlerAsync 작업이 강제로 실행됩니다. AsyncOp의 재진입 기능을 보여주기 위해 Task.Delay 메서드를 비동기식으로 사용합니다.
이 솔루션은 작업 순서 지정 및 재진입을 관리하는 강력하고 효율적인 방법을 제공하여 명령이 도착 속도에 상관없이 원하는 순서대로 실행됩니다.
위 내용은 AsyncOp는 멀티스레드 환경에서 작업 순서 지정 및 재진입을 어떻게 효율적으로 관리할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!