इस कोड में एसिंक्रोनी को सही ढंग से कैसे कार्यान्वित करें?


एक इकाई “कार्य” है। इसमें निम्नलिखित गुण हैं:
– निष्पादक पर लोड – int (1 से 5 तक);
– निष्पादन समय (सेकंड) – पूर्णांक।
ये कार्य वितरक (लोड बैलेंसर) द्वारा प्राप्त किये जाते हैं। ऐसे निष्पादक भी हैं जो लोड बैलेंसर से कार्य प्राप्त करते हैं और उन्हें निष्पादित करते हैं। निष्पादकों के पास निम्नलिखित पैरामीटर हैं:
– एक साथ निष्पादित कार्यों की अधिकतम संख्या – int;
– अधिकतम कुल भार – पूर्णांक।

निष्पादक कार्य को “निष्पादन समय (सेकंड)” समय के लिए निष्पादित करता है, जो कार्य गुणों में वर्णित है। लोड बैलेंसर कतार से कार्य लेता है और उन्हें निष्पादकों के बीच वितरित करता है। कार्य केवल उन्हीं निष्पादकों को वितरित किए जा सकते हैं, जिनके पास कार्यों के लिए आवश्यक क्षमता का भंडार और मुफ्त स्लॉट का भंडार है। वितरण यथासंभव समान होना चाहिए। ऐसा नहीं होना चाहिए कि एक परफॉर्मर पूरी तरह से लोडेड हो और बाकी लोग आराम कर रहे हों।

– कंसोल में एक दृश्य दृश्य होना चाहिए जो प्रत्येक निष्पादक का कार्यभार (प्रदर्शन किए गए कार्यों की संख्या, कितने संसाधनों पर कब्जा/मुक्त) और कतार में कार्यों की संख्या दिखाता है;
– एसिंक्रोनसी लागू किया जाना चाहिए (सभी निष्पादकों को समानांतर में काम करना चाहिए);
– कार्यक्रम की शुरुआत में कार्यों की एक कतार बनाई जानी चाहिए, जिसे आगे बैलेंसर द्वारा पढ़ा जाएगा और निष्पादकों को भेजा जाएगा

मेरी समस्या अतुल्यकालिक का गलत उपयोग है। निष्पादकों को समानांतर रूप से काम करना चाहिए. इसे सही तरीके से कैसे क्रियान्वित करें?

मैंने क्या प्रयास किया है:

सी#
public class TaskEntity
{
    public int Load { get; set; }
    public int ExecutionTime { get; set; }

    public TaskEntity(int load, int executionTime)
    {
        Load = load;
        ExecutionTime = executionTime;
    }
}

public class Executor
{
    public int MaxTasks { get; set; }
    public int MaxLoad { get; set; }
    public int CurrentLoad { get; set; }
    public List<TaskEntity> CurrentTasks { get; set; }
    public Executor(int maxTasks, int maxLoad)
    {
        MaxTasks = maxTasks;
        MaxLoad = maxLoad;
        CurrentLoad = 0;
        CurrentTasks = new List<TaskEntity>();
    }
}

public class LoadBalancer
{
    private readonly List<Executor> Executors;
    private readonly Queue<TaskEntity> TaskQueue;

    public LoadBalancer(List<Executor> executors)
    {
        Executors = executors;
        TaskQueue = new Queue<TaskEntity>();
    }

    public async Task StartAsync()
    {
        while (true)
        {
            if (TaskQueue.Count > 0)
            {
                var task = TaskQueue.Dequeue();
                var availableExecutor = GetAvailableExecutor(task);

                if (availableExecutor != null)
                {
                    await ExecuteTaskAsync(task, availableExecutor);
                }
            }

            DisplayLoadStatus();
            await Task.Delay(1000); 
        }
    }

    public void EnqueueTask(TaskEntity task)
    {
        TaskQueue.Enqueue(task);
    }

    private Executor GetAvailableExecutor(TaskEntity task)
    {
        return Executors.Find(e => e.CurrentLoad + task.Load <= e.MaxLoad &&
                                     e.CurrentTasks.Count < e.MaxTasks);
    }

    private async Task ExecuteTaskAsync(TaskEntity task, Executor executor)
    {
        executor.CurrentLoad += task.Load;
        executor.CurrentTasks.Add(task);

        await Task.Delay(task.ExecutionTime * 1000);

        executor.CurrentLoad -= task.Load;
        if (executor.CurrentTasks.Contains(task))
        {
            executor.CurrentTasks.Remove(task);
        }
    }

    private void DisplayLoadStatus()
    {
        Console.Clear();
        foreach (var executor in Executors)
        {
            Console.WriteLine($"Executor {Executors.IndexOf(executor) + 1}:");
            Console.WriteLine($"  - Current Workload: {executor.CurrentLoad}/{executor.MaxLoad}");
            Console.WriteLine($"  - Concurrent Tasks: {executor.CurrentTasks.Count}/{executor.MaxTasks}");
            Console.WriteLine();
        }

        Console.WriteLine($"Task Queue Size: {TaskQueue.Count}");
    }



static async Task Main()
{
    var executorCount = 3; 
    var executors = new List<Executor>();

    for (int i = 0; i < executorCount; i++)
    {
        executors.Add(new Executor(maxTasks: 2, maxLoad: 10));
    }

    var loadBalancer = new LoadBalancer(executors);

    var loadBalancerTask = loadBalancer.StartAsync();

    var random = new Random();
    for (int i = 0; i < 10; i++)
    {
        var task = new TaskEntity(load: random.Next(1, 6), executionTime: random.Next(1, 6));

        loadBalancer.EnqueueTask(task);
        await Task.Delay(1000); 
    }

    await loadBalancerTask;
}

समाधान 1

जब आप कई कार्यों को इनलाइन चलाना चाहते हैं, तो आपको प्रत्येक कार्य का एक संदर्भ रखना होगा और उसका इंतजार नहीं करना होगा। प्रत्येक कार्य की प्रतीक्षा करने से वे क्रमिक रूप से चलने लगेंगे।

यहां नौकरियों को इनलाइन चलाने का एक सरल उदाहरण दिया गया है।

1. नौकरी:

सी#
class Job
{
    public string Id { get; }
    public int Runtime { get; }

    public Job(string id, int runtime)
    {
        Id = id;
        Runtime = runtime;
    }

    public async Task<Job> ExecuteAsync()
    {
        await Task.Yield();

        int elapsed = 0;
        TimeSpan delay = TimeSpan.FromSeconds(1);

        while (elapsed < Runtime)
        {
            Console.WriteLine($"{Id} ping {elapsed++} of {Runtime}");
            await Task.Delay(delay);
        }

        Console.WriteLine($"{Id} ping {elapsed++} of {Runtime}");
        return this;
    }
}

प्रबंधक:

सी#
var tasks = new List<Task<Job>>();

var rand = new Random();

for (int i = 0; i < 10; i++)
{
    Job job = new Job($"Task {i}", rand.Next(3, 6));

    tasks.Add(job.ExecuteAsync());
}

while (true)
{
    Task.WaitAny(tasks.ToArray());

    foreach (Task<Job> task in tasks.Where(
        x => x.IsCompleted || x.IsCanceled || x.IsFaulted).ToList())
    {
        var completedJob = await task;
        Console.WriteLine($"!! Job{completedJob.Id} completed");
        tasks.Remove(task);
    }

    if (tasks.Count == 0)
        break;
}

इससे आपको अपना कोड अपडेट करने में मदद करने की अवधारणा मिलनी चाहिए।

コメント

タイトルとURLをコピーしました