Rumah > pembangunan bahagian belakang > C++ > Bagaimanakah AsyncOp Boleh Menguruskan Penjujukan Tugasan dan Kemasukan Semula dengan Cekap dalam Persekitaran Berbilang Thread?

Bagaimanakah AsyncOp Boleh Menguruskan Penjujukan Tugasan dan Kemasukan Semula dengan Cekap dalam Persekitaran Berbilang Thread?

Linda Hamilton
Lepaskan: 2025-01-04 20:13:49
asal
251 orang telah melayarinya

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

Penjujukan Tugasan dan Kemasukan Semula: Mengurus Perintah Berjujukan dalam Persekitaran Berbilang Thread

Dalam aplikasi perisian dunia sebenar, adalah perkara biasa untuk menghadapi senario di mana tugas dikendalikan secara berurutan, dan susunan pelaksanaannya adalah kritikal. Penjujukan tugasan menjadi lebih kompleks apabila tugasan mungkin tiba lebih cepat daripada yang boleh diproses, dan ia dimasukkan semula, bermakna ia boleh dilaksanakan serentak dalam diri mereka sendiri.

Pertimbangkan senario berikut:

  1. Tugas pengendali arahan UI boleh diselesaikan secara serentak atau tidak segerak.
  2. Arahan boleh tiba pada kadar yang lebih cepat daripada yang diproses.
  3. Jika tugas yang belum selesai sudah wujud untuk sesuatu arahan, tugasan pengendali arahan baharu hendaklah digilir dan dilaksanakan secara berurutan.
  4. Hasil setiap tugasan baharu mungkin bergantung pada hasil tugasan sebelumnya.

Secara tradisinya, isu Sync-or-Async boleh diatasi dengan menggunakan kaedah Task.Factory.StartNew dengan parameter TaskScheduler.FromCurrentSynchronizationContext() untuk memaksa pelaksanaan tak segerak. Walau bagaimanapun, pendekatan ini mungkin tidak sesuai jika pengendali arahan direka bentuk untuk melaksanakan secara serentak secara dalaman.

Untuk menangani cabaran ini, kelas tersuai yang dipanggil AsyncOp boleh dilaksanakan. AsyncOp mengendalikan penjujukan tugas dan keperluan kemasukan semula. Berikut ialah versi kemas kini kelas AsyncOp dengan ciri tambahan:

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));
        }
    }
}
Salin selepas log masuk

Versi yang dikemas kini ini menyediakan peningkatan berikut:

  • Masuk semula : AsyncOp kini menyokong kemasukan semula dengan membenarkan nested tugasan.
  • Keselamatan benang: Kunci digunakan untuk melindungi medan _pending.
  • Batal/Mulakan Semula: Baharu HandleCancelAsync dan Kaedah HandleRestartAsync membolehkan anda membatalkan atau memulakan semula jujukan tugasan dengan anggun.

Menggunakan kelas AsyncOp yang dikemas kini ini, kod sampel yang disediakan dalam soalan boleh ditulis semula seperti berikut:

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();
        }
    }
}
Salin selepas log masuk

Dalam versi yang dikemas kini ini, tugasan handleAsync terpaksa dijalankan secara tak segerak menggunakan kaedah Task.Delay untuk menunjukkan keupayaan kemasukan semula AsyncOp.

Penyelesaian ini menyediakan cara yang mantap dan cekap untuk mengurus penjujukan tugasan dan kemasukan semula, memastikan bahawa arahan dilaksanakan dalam susunan yang diingini, tanpa mengira kadar ia tiba.

Atas ialah kandungan terperinci Bagaimanakah AsyncOp Boleh Menguruskan Penjujukan Tugasan dan Kemasukan Semula dengan Cekap dalam Persekitaran Berbilang Thread?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan