Bloqueo y/o sincronizacion de servicios con IHostedService

Roberlan 0 Puntos de reputación
2024-05-28T07:58:57.8966667+00:00

Buenos dias:

Tengo un proyecto en C# .NET 8 donde tengo varios servicios (mas de 2) IHostedServices corriendo en segundo plano. Cada uno hace algo diferente. Mi duda es como podria bloquear o sincronizar los servicios cuando uno se esta ejecutando?… Me explico: todos estos servicios escriben en BD y son un poco pesados (4 o 5 segundo…quizas mas). Mi idea es que solo se ejecute uno a la vez, sin prioridades, tipo cola FIFO, para evitar algun bloqueo en BD porque ejecutan stored procedures muy grandes y en algunas partes tienen tablas comunes.

gracias de antemano

ASP.NET
ASP.NET
Conjunto de tecnologías de .NET Framework para la creación de aplicaciones y servicios web XML.
46 preguntas
0 comentarios No hay comentarios
{count} votos

1 respuesta

Ordenar por: Muy útil
  1. Gao Chen 4,385 Puntos de reputación Proveedor de Microsoft
    2024-12-21T00:13:40.6833333+00:00

    Hola Roberlan,

    ¡Bienvenido(a) a Microsoft Q&A!

    Lamentamos mucho la demora en darle una respuesta a tu tema en este foro. Si todavía tienes la misma consulta, para sincronizar tus IHostedService en un proyecto C# .NET 8 y asegurarte de que solo uno se ejecute a la vez, puedes implementar un mecanismo de bloqueo utilizando una cola FIFO. Aquí tienes una forma de hacerlo:

    Crear una clase de cola de tareas:

    • Esta clase gestionará las tareas en una cola y se asegurará de que solo una tarea se ejecute a la vez.
    public class TaskQueue
    {
        private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        private readonly Queue<Func<Task>> _tasks = new Queue<Func<Task>>();
    
        public async Task Enqueue(Func<Task> taskGenerator)
        {
            await _semaphore.WaitAsync();
            try
            {
                _tasks.Enqueue(taskGenerator);
                if (_tasks.Count == 1)
                {
                    _ = ProcessQueue();
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }
    
        private async Task ProcessQueue()
        {
            while (_tasks.Count > 0)
            {
                var taskGenerator = _tasks.Dequeue();
                await taskGenerator();
            }
        }
    }
    

    Modificar tus IHostedService para usar la cola:

    • En cada uno de tus servicios, en lugar de ejecutar directamente la lógica, encola la tarea en la TaskQueue.
    public class MyHostedService : IHostedService
    {
        private readonly TaskQueue _taskQueue;
    
        public MyHostedService(TaskQueue taskQueue)
        {
            _taskQueue = taskQueue;
        }
    
        public Task StartAsync(CancellationToken cancellationToken)
        {
            _taskQueue.Enqueue(async () =>
            {
                // Tu lógica aquí
                await Task.Delay(5000); // Simulación de trabajo pesado
            });
    
            return Task.CompletedTask;
        }
    
        public Task StopAsync(CancellationToken cancellationToken)
        {
            // Lógica para detener el servicio si es necesario
            return Task.CompletedTask;
        }
    }
    

    Registrar la TaskQueue y los servicios en Startup:

    • Asegúrate de registrar la TaskQueue como un singleton y tus IHostedService en el contenedor de dependencias.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<TaskQueue>();
        services.AddHostedService<MyHostedService>();
        // Registrar otros servicios
    }
    

    Con esta configuración, cada servicio encolará su tarea en la TaskQueue, y las tareas se ejecutarán una a la vez en el orden en que fueron encoladas, evitando así bloqueos en la base de datos.

    Adicionalmente, por favor ten cuenta que si no fuéramos a recibir una respuesta a este hilo en 2 días hábiles, entonces consideraríamos estos hilos como cerrados, en caso de que tengas la misma consulta y la información proporcionada no sea útil, no dudes en crear otro hilo y estaremos más que felices de ayudarle.

    Atentamente,

    Gao


    Si esta respuesta resolvió tu consulta, por favor haz clic en 'Aceptar respuesta'. Esto nos ayuda a mejorar continuamente la calidad y relevancia de nuestras soluciones.

    0 comentarios No hay comentarios

Su respuesta

Las respuestas se pueden marcar como respuestas aceptadas por el autor de la pregunta, lo que ayuda a los usuarios a conocer la respuesta que resolvió el problema del autor.