multithreading – Multithreaded Modular System Architecture for .NET

Question:

So, for example, there is a game – a football simulator.
There is a global object for the game session, which includes a list of football clubs, players in them, etc. There are thousands and thousands of data.

The root element of the game is something like this:

public async void Run(ISession session)
    {
        while (true)
        {
            dynamic result = await session.Go();

            if (result.ReadyToAction)
            {
                _gameControlEvent.WaitOne();
            }
        }
    }

Those. some global data is being processed in the game, and then the user reacts to this in some way, and the same thing continues. Endlessly.
The fact is that the game is being developed gradually, and the functionality is expanding. Therefore, there are some modules (a module is a class that receives an object with data as input, and it processes them. It can both read and write to this object) that actually process this large information.

public async Task<GoResult> Go()
    {
        ...

        foreach (var module in _modules.OrderBy(x => x.Priority))
        {
            results.Add(module.ProcessGameData(GameData));
        }

        ..

        CurrentDate = CurrentDate.AddDays(1);
    }

GameData is our global object.

The question is how best to organize such an architecture?

Suppose now there is a module "Transfers", and in the future I will add a module that should wait for the result of processing some other modules. For example, I will add a module – News, and it must wait for the result of the execution of the Transfers, Renewal of the contract, etc. modules. Those. how to organize such dependencies between handlers.

It is understood that each module can run in a separate thread. Maybe there are already any structured algorithms out there like this?

All for some reason answer the typical multithreaded questions. I'm not asking about that.

A rigid structure is not needed. It is necessary that adding a module does not change the functionality of the system in any way. That is, you write a module, add dependencies and everything works by itself.

class TransferModule{ 
    TransferModule(INewsModule newsModule){
    //модуль трансфера отработает только после того, как завершиться выполнения модуля News     
    }

}

Answer:

I think you will need to resort to Task.ContinueWith to solve this problem .

Here's a sketch.

    public interface IGlobalData
    {

    }

    public class GlobalData : IGlobalData
    {

    }

    public interface IModule
    {
        IGlobalData ProcessGameData(IGlobalData globalData);
    }

    public class Module : IModule
    {
        public virtual IGlobalData ProcessGameData(IGlobalData globalData)
        {
            return globalData;
        }
    }

    public class News : Module
    {
        public override IGlobalData ProcessGameData(IGlobalData globalData)
        {
            Console.WriteLine("News");
            return base.ProcessGameData(globalData);
        }
    }

    public class Transfers : Module
    {
        public override IGlobalData ProcessGameData(IGlobalData globalData)
        {
            Console.WriteLine("Transfers");
            return base.ProcessGameData(globalData);
        }
    }

    public class AnotherModule : Module
    {
        public override IGlobalData ProcessGameData(IGlobalData globalData)
        {
            Console.WriteLine("AnotherModule");
            return base.ProcessGameData(globalData);
        }
    }

    class Continuations
    {
        static void Main()
        {
            var globalData = new GlobalData();

            var rootTask = new Task<IGlobalData>(() => new Transfers().ProcessGameData(globalData));
            var newsTask = rootTask.ContinueWith(t => new News().ProcessGameData(t.Result));
            var anptherTask = newsTask.ContinueWith(t => new AnotherModule().ProcessGameData(t.Result));

            rootTask.Start();
            Console.ReadKey();
        }
    }
Scroll to Top