ホームページ > バックエンド開発 > C++ > AsyncOp はマルチスレッド環境でタスクのシーケンスと再入を効率的に管理するにはどうすればよいですか?

AsyncOp はマルチスレッド環境でタスクのシーケンスと再入を効率的に管理するにはどうすればよいですか?

Linda Hamilton
リリース: 2025-01-04 20:13:49
オリジナル
251 人が閲覧しました

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

タスクの順序付けと再入: マルチスレッド環境での順次コマンドの管理

実際のソフトウェア アプリケーションでは、次のようなシナリオに遭遇するのが一般的です。タスクは順番に処理され、実行順序が重要です。タスクが処理できるより早く到着する可能性があり、タスクがリエントラントである、つまりタスク自体内で同時に実行できる場合、タスクのシーケンスはさらに複雑になります。

次のシナリオを考えてみましょう:

  1. UI コマンド ハンドラー タスクは、同期または非同期で完了できます。
  2. コマンドは、処理される速度よりも速い速度です。
  3. コマンドに対して保留中のタスクがすでに存在する場合、新しいコマンド ハンドラー タスクはキューに入れられ、順番に実行される必要があります。
  4. 各新しいタスクの結果は、次の条件に依存する可能性があります。前のタスクの結果。

従来、同期または非同期の問題は、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();
        }
    }
}
ログイン後にコピー

この更新されたバージョンでは、handleAsync タスクが強制的に実行されます。 Task.Delay メソッドを非同期的に使用して、AsyncOp の再入機能を実証します。

このソリューションは、タスクの順序付けと再入を管理する堅牢かつ効率的な方法を提供し、コマンドが到着速度に関係なく、希望の順序で実行されます。

以上がAsyncOp はマルチスレッド環境でタスクのシーケンスと再入を効率的に管理するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート