首頁 > 後端開發 > C++ > AsyncOp 如何在多執行緒環境中有效管理任務排序和重入?

AsyncOp 如何在多執行緒環境中有效管理任務排序和重入?

Linda Hamilton
發布: 2025-01-04 20:13:49
原創
250 人瀏覽過

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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板