Ejercicio I02 - Simulador de atención a clientes
Consigna
Se creará una solución para simular la atención paralela de clientes en dos cajas de un negocio.
Empezar creando un proyecto de biblioteca de clases y declarar las siguientes clases:
Caja
Tendrá un atributo estático de tipo
Random
que será instanciado en un constructor estático.Tendrá un atributo de tipo
Queue<string>
llamadoclientesALaEspera
.Tendrá un atributo de tipo
string
llamadonombreCaja
que será expuesto por una propiedad de sólo lectura.Tendrá una propiedad
CantidadDeClientesALaEspera
que retornará la cantidad actual de elementos en la colaclientesALaEspera
.El único constructor de instancia deberá:
- Instanciar la cola
clientesALaEspera
. - Recibir el nombre de la caja y asignarlo al atributo
nombreCaja
. - Recibir la referencia a un método que no retorne nada y reciba un objeto de tipo
Caja
y otro de tipostring
. Dicha referencia deberá asignarse a un campo privado llamadodelegadoClienteAtendido
. Declarar un nuevo tipo delegado que permita cumplir con este punto.
- Instanciar la cola
Tendrá un método
AgregarCliente
con visibilidadinternal
que recibirá un cliente y lo agregará aclientesALaEspera
.Tendrá un método
IniciarAtencion
con visibilidadinternal
que deberá iniciar la atención de clientes en un sub-proceso paralelo. Este método no recibirá nada y retornará la instancia deTask
que se haya utilizado.- La tarea de atención de clientes:
- Se seguirá ejecutando de manera iterativa hasta que se cierre la aplicación.
- Si hay clientes a la espera (se puede verificar con el método
Any
de la biblioteca LINQ (System.Linq
) que retornatrue
si una colección contiene algún elemento.):- Se retirará al siguiente cliente de la cola
clientesALaEspera
. - Se invocará al método referenciado por
delegadoClienteAtendido
, pasándole la instancia de esa misma caja y el cliente que se recuperó de la cola. - Se suspenderá el hilo por un periodo de 1 a 5 segundos de manera aleatoria (usar atributo
Random
).
- Se retirará al siguiente cliente de la cola
- La tarea de atención de clientes:
Negocio
Requerirá la instalación del paquete NuGet
NameGenerator
en el proyecto de biblioteca de clases.Crear un atributo estático de tipo
RealNameGenerator
(namespaceNameGenerator.Generators
) que será instanciado en un constructor estático.Tendrá un atributo de tipo
ConcurrentQueue<string>
llamadoclientes
. Este tipo de dato es la versión del tipoQueue
que cuenta con seguridad para trabajar con hilos (es thread-safe).
Tendrá un atributo de tipo
List<Caja>
llamadocajas
.El único constructor de instancia deberá:
- Recibirá una lista de cajas y la asignará al atributo
cajas
. - Instanciará el atributo
clientes
.
- Recibirá una lista de cajas y la asignará al atributo
Tendrá un método público
ComenzarAtencion
que:- Lo primero que hará será abrir todas las cajas del negocio, llamando al método
IniciarAtencion
de cada caja. - En segundo lugar iniciará una tarea concurrente (en otro hilo) de simulación de clientes.
- La tarea se seguirá ejecutando de manera iterativa hasta que se cierre la aplicación.
- Esta tarea deberá agregar un nuevo cliente a la cola
clientes
cada un segundo (suspender 1 segundo el hilo). - Para generar el nuevo cliente utilizar el método
Generate
del atributo estático de tipoRealNameGenerator
.
- En tercer lugar iniciará una tarea concurrente (en otro hilo) de asignación de cajas. Esta tarea asignará al siguiente cliente en la cola
clientes
a la caja con MENOS clientes .- La tarea se seguirá ejecutando de manera iterativa hasta que se cierre la aplicación.
- Para saber cuál es la caja con menos clientes, ordenar las cajas de forma ascendente en base a la propiedad
CantidadDeClientesALaEspera
.- Utilizar el método
OrderBy
de la biblioteca LINQ (System.Linq
), que tiene como argumento un delegado que recibe un cliente y retorna el valor esa instancia por el que se debe ordenar (en este caso la propiedadCantidadDeClientesALaEspera
). Ante cualquier duda, consulte la documentación.
- Utilizar el método
- Una vez ordenada la lista debemos quedarnos con la caja con menos clientes a la espera, es decir, la primera luego de haber ordenado de forma ascendente. Para esto utilizar el método
First
de la biblioteca LINQ (System.Linq
), que retorna el primer elemento de una colección. Ante cualquier duda, consulte la documentación. - Para recuperar el cliente de la cola
clientes
utilizar el métodoTryDequeue
. - Si el método
TryDequeue
retornó unstring
que no sea nulo ni espacios en blanco (puede usar el método estáticostring.IsNullOrWhiteSpace
), agregar el cliente a la caja utilizando el métodoAgregarCliente
de la caja.
- No recibirá nada y retornará la lista de sub-procesos iniciados por el negocio (
List<Task>
). Esta lista debe incluir los hilos iniciados para la simulación de clientes, la asignación de cajas y los retornados por el métodoIniciarAtencion
de las cajas.
- Lo primero que hará será abrir todas las cajas del negocio, llamando al método
Crear una aplicación de consola y en el método Main
:
Instanciar el delegado declarado en
Caja
con una expresión lambda que imprima un mensaje en la consola con el siguiente formato:[Hora actual con formato HH:MM:ss] - Hilo [Id del hilo actual (usar `Task.CurrentId`)] - [Nombre de la caja] - Atendiendo a [nombre del cliente]. Quedan [cantidad de clientes a la espera] clientes en esta caja.
Ejemplo de resultado esperado: "13:10:31 - Hilo 1 - Caja 01 - Atendiendo a Christopher Torres. Quedan 2 clientes en esta caja."
Reemplazar el texto entre corchetes por el dato correspondiente.
Instanciar 2 cajas, pasándole al constructor el delegado instanciado en el punto anterior.
Instanciar una variable de tipo
List<Caja>
y agregarle las cajas creadas en el punto anterior.Instanciar un
Negocio
y pasarle la lista de cajas del punto anterior.Imprimir por consola el texto: "Asignando cajas..."
Llamar al método
ComenzarAtencion
deNegocio
.Utilizar el método estático
WaitAll
deTask
para que la aplicación no se cierre mientras los hilos retornados por el métodoComenzarAtencion
estén corriendo. Tener en cuenta queWaitAll
recibe un array como argumento y no una lista (usar el métodoToArray
para convertir la lista en un array).
Resolución
Video | Código |
---|