> 백엔드 개발 > C++ > AsyncOp는 멀티스레드 환경에서 작업 순서 지정 및 재진입을 어떻게 효율적으로 관리할 수 있습니까?

AsyncOp는 멀티스레드 환경에서 작업 순서 지정 및 재진입을 어떻게 효율적으로 관리할 수 있습니까?

Linda Hamilton
풀어 주다: 2025-01-04 20:13:49
원래의
252명이 탐색했습니다.

How Can AsyncOp Efficiently Manage Task Sequencing and Re-Entrancy in Multithreaded Environments?

작업 순서 지정 및 재진입: 다중 스레드 환경에서 순차적 명령 관리

실제 소프트웨어 애플리케이션에서는 시나리오에 직면하는 것이 일반적입니다. 작업이 순차적으로 처리되며 실행 순서가 중요합니다. 작업이 처리 가능한 것보다 빨리 도착하고 재진입이 가능해지면 작업 순서 지정이 훨씬 더 복잡해집니다. 즉, 작업 자체 내에서 동시에 실행할 수 있다는 뜻입니다.

다음 시나리오를 고려해 보세요.

  1. UI 명령 처리기 작업은 동기식 또는 비동기식으로 완료될 수 있습니다.
  2. 명령은 실제보다 빠른 속도로 도착할 수 있습니다. 처리됩니다.
  3. 명령에 대해 보류 중인 작업이 이미 있는 경우 새 명령 처리기 작업을 대기열에 추가하고 순차적으로 실행해야 합니다.
  4. 각 새 작업의 결과는 이전 작업의 결과에 따라 달라질 수 있습니다. task.

일반적으로 동기 또는 비동기 문제는 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 이제 중첩을 허용하여 재진입을 지원합니다. 작업.
  • 스레드 안전성: 잠금은 _pending 필드를 보호하는 데 사용됩니다.
  • 취소/다시 시작: 신규 HandleCancelAsyncHandleRestartAsync 메서드를 사용하면 작업 순서를 정상적으로 취소하거나 다시 시작할 수 있습니다.

이 업데이트된 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿