
Como sabemos, es muy sencillo implementar servicios en segundo plano alojados en el interior de aplicaciones ASP.NET Core porque el framework nos proporciona infraestructura que simplifica la tarea, permitiendo que nos enfoquemos en la lógica de negocio que queremos ejecutar en background en lugar de tener que preocuparnos de los aspectos de más bajo nivel necesarios para hacer que funcione.
En la práctica, basta con heredar de la clase BackgroundService
y sobreescribir el método ExecuteAsync
para implementar la lógica que queremos ejecutar en segundo plano. Por ejemplo, el siguiente servicio se encarga de escribir un mensaje en la consola cada segundo:
public class MyBackgroundService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine($"Current time: {DateTime.Now:T}");
await Task.Delay(1000, stoppingToken);
}
}
}
Luego tendríamos registrar este servicio en el contenedor de dependencias de ASP.NET Core, de forma que el framework lo detectará automáticamente y lo lanzará cuando la aplicación sea iniciada:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHostedService<MyBackgroundService>();
...
Al ejecutar, veremos que, en la consola donde hemos lanzado la aplicación, se escribirá periódicamente la hora desde la tarea en segundo plano:
Current time: 13:34:06
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7080
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5148
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: D:\Projects\BackgroundServiceCrash
Current time: 13:34:07
Current time: 13:34:08
Pero bueno, no es esto de lo que quería hablar, sino de lo que ocurre cuando en uno de estos servicios en segundo plano se produce un error... porque ojo, que si no tenemos cuidado puede tumbar completamente nuestra aplicación.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: aspnetcore, trucos

Estrenamos febrero con la recopilación número 595 de enlaces interesantes, cargado de contenidos variados y de calidad relacionado con el desarrollo de software: .NET, ASP.NET, Azure, conceptos, patrones y buenas prácticas, IA, programación web (HTML, CSS, Javascript, frameworks), Visual Studio y herramientas, .NET MAUI, y otros.
Sin duda, la sorpresa y gran protagonista de la semana ha sido el lanzamiento de DeepSeek R1, la IA open source que ha puesto patas arriba a los que hasta ahora se consideraban los reyes del mambo, demostrando que China compite en primera división de los modelos generativos.
También es interesante echar un vistazo bajo el capó de los navegadores, a los mecanismos encargados de interpretar los para interpretar el código HTML y CSS que les llega y crear su representación visual. Aditya Bhattacharya nos lo cuenta el artículo HTML & CSS Deep Dive Part 1: How Browsers Make Sense of Your Code.
Sergey Teplyakov nos recuerda en el post The Dangers of Async Void lo peligroso que puede ser crear métodos o funciones async void
en C#, una práctica que puede llegar a tumbar por completo una aplicación.
El amigo Braulio Díez vuelve con sus historias para no dormir, con el artículo Las migraciones tienen veneno, una visión práctica y realista de lo que hay detrás de estos proyectos que, aunque a primera vista pueden parecer sencillos, tienen bastantes trampas ocultas.
Por último, desde CampusMVP nos llega un post que abre los ojos sobre la realidad del open source: ¿es gratis? ¿quién lo mantiene? ¿quién contribuye? ¿Es sostenible? Muchas preguntas interesantes a las que podremos dar respuesta en el post y vídeo donde José Manuel Alarcón y Jorge Turrado debaten sobre el tema.
El resto de enlaces, a continuación 🙂
Por si te lo perdiste...
- ¡No guardes como cadena el resultado JSON de la llamada a una API si lo único que quieres hacer es deserializarla!
José M. Aguilar - Personalizar la negociación de contenidos en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- When will .NET Framework retire?
Steven Giesel - Implementing AES Encryption With C#
Milan Jovanović - How Fast is Microsoft C#? Discover the Advantages
Dave Ward - Moving from .NET 6 to 8
Joao Correia - Supporting multiple .NET SDK versions in analyzers and source generators
Andrew Lock - The New LINQ Methods from .NET 6 to .NET 9
Anton Martyniuk - Writing a .NET Garbage Collector in C#
Kevin Gosse - The Dangers of Async Void
Sergey Teplyakov - Useful New-ish Features in .NET/C#
David Ramel

Habitualmente los paquetes NuGet que usamos en un proyecto se registran en entradas <PackageReference>
de su archivo .csproj
. Es un mecanismo sencillo y efectivo cuando trabajamos con un único proyecto o un número reducido de ellos.
Sin embargo, cuando la cosa crece y estamos trabajando con muchos proyectos que usan paquetes comunes cuyas versiones deben estar alineadas, todo se complica un poco, y trabajar con ellos se puede convertir en algo bastante tedioso. Y más aún si no usamos una herramienta visual como NuGet Package Manager de Visual Studio.
Para estos escenarios, NuGet 6.2, lanzado en agosto de 2023 y presente por defecto en todas las instalaciones actualizadas de .NET y Visual Studio, introdujo el concepto de gestión centralizada de paquetes (en inglés, Central Package Management o CPM). Esta funcionalidad nos brinda la posibilidad de definir en un archivo independiente los paquetes utilizados, con sus versiones correspondientes, de forma que todos los proyectos de la solución puedan hacer referencia a él y mantener sus dependencias actualizadas.

Aquí tenemos la entrega número 594 de enlaces a contenidos interesantes que he ido recopilando durante la semana, con mucho .NET, ASP.NET Core, IA, Azure, JavaScript, CSS, herramientas de desarrollo y más.
En esta ocasión me gustaría destacar el post de Neo Kim sobre cómo funciona Bluesky. Me encantan estos posts que detallan los engranajes que hay por detrás de aplicaciones que todos conocemos y que tienen unos requisitos altísimos de escalabilidad y rendimiento.
También me ha resultado muy interesante el post de Milan Jovanović sobre cómo escalar monolitos, porque creo que puede ser de utilidad si tenéis aplicaciones que con el tiempo han ido creciendo más allá de lo que se esperaba en un principio.
También en la sección "cómo funcionan las cosas que usamos todos los días" 😉, el post de Moncef Abboud es muy interesante para profundizar un poco en los algoritmos de compresión más habituales.
Por último, me ha hecho ilusión ver que NDepend sigue evolucionando e introduciendo mejoras para ofrecer perspectivas únicas de nuestras bases de código. Vale la pena echarle un vistazo.
Y ahora, a por el resto...
Por si te lo perdiste...
- Invocar View Componentes usando Tag Helpers en ASP.NET Core MVC
José M. Aguilar - Usar kebab-case en rutas de aplicaciones ASP.NET Core MVC y Razor Pages
José M. Aguilar
.NET Core / .NET
- Why C# Developers Should Also Learn Rust, and What It Can Teach Them
Darren Horrocks - Announcing ConsoleApplicationBuilder, DI in console applications, simply
Peter Ritchie - Accessing MSBuild properties and user configuration from source generators
Andrew Lock - WinForms: Analyze This (Me in Visual Basic)
Klaus Loeffelmann - Seamless Slide Conversion: PowerPoint to Images in C#
Dharanya Sakthivel - Using Roslyn to analyze and rewrite code in a solution
Gérald Barré - The Disposable Pattern in ASP.NET Core
Ricardo Peres - C# Tip: How to create Custom Attributes, and why they are useful
Davide Bellone - Mastering BenchmarkDotNet: The Essential Benchmarking Library for .NET Developers
Jayraj Chhaya - 5 Effective Ways to Navigate PDF Pages in C# Using .NET PDF Library
Chinnu Muniyappan

En general, el uso de expresiones largas debería estar prohibido por ley. Hay pocas cosas que ataquen tanto a la legibilidad de un código como una expresión larga y compleja a la que tengamos que dedicar un buen rato cada vez que intentemos comprenderla. Y no digamos si nos toca modificarla 😱
Aunque esto es aplicable a cualquier tipo de expresión, en este post me voy a centrar en los predicados, que al fin y al cabo representan las condiciones que determinan el comportamiento de una aplicación.
Veamos un ejemplo de if
con un predicado que implementa una condición de negocio necesaria para que un usuario user
pueda realizar una tarea concreta en la cuenta account
:
if (account is not null && account.IsActive && account.HasSubscription
&& account.SubscriptionStartDate <= DateTime.Today && account.SubscriptionEndDate
>= DateTime.Now.AddDays(1) && (account.SubscriptionLevel == "Standard" ||
account.SubscriptionLevel == "Premium") && user.IsActive && (user.HasRole("admin")
|| (user.HasRole("owner"))) && user.AccountId == account.Id)
{
account.ChangePaymentMethod("paypal");
}
Es un poco difícil de leer, ¿verdad? 😅 Bueno, está algo forzado para ilustrar bien el ejemplo, pero seguro que en nuestras bases de código podríamos reconocer fragmentos conceptualmente similares.
Básicamente, la condición anterior verifica si el estado de la cuenta account
es válido para realizar la tarea, comprobando que sea correcta, esté activa, y tenga en vigor una suscripción de nivel "Standard" o "Premium", así como que el usuario user
tenga permisos para hacerlo, comprobando que esté activo, tenga un rol de "admin" u "owner", y pertenezca a la cuenta account
.
Obviamente, no podemos evitar que la lógica de negocio sea compleja, eso no depende de nosotros. Pero sí podemos hacer que la forma de expresarla mediante código sea más sencilla y legible, así que, ¡manos a la obra!

Aquí está la recopilación semanal número 593 de enlaces interesantes, donde podéis encontrar un montón de referencias a artículos sobre C#, .NET, ASP.NET, Azure, desarrollo web, inteligencia artificial, Visual Studio y otros temas 🙂
Destacable el post "Tendencias en programación JavaScript para 2025", de José Manuel Alarcón, donde desvela hacia dónde se dirige el desarrollo JavaScript este año recién estrenado, en términos de herramientas, frameworks, metaframeworks, programación en backend y los nuevos paradigmas impulsados por la irrupción de la inteligencia artificial. Si usáis este lenguaje y su ecosistema, no os lo perdáis.
Los que diseñáis sistemas distribuidos con ASP.NET Core, os puede venir bien echar un vistazo a la introducción de Ricardo Peres a la implementación de trazas distribuidas en ASP.NET Core.
El artículo de Mark Heath sobre el uso de tools de forma segura con LLMs, Using Tools (Safely) with LLMs, me ha sido útil para descubrir que las bibliotecas cliente de Azure OpenAI también tienen la capacidad de ejecutar herramientas, algo que pensaba que había que hacer manualmente o con frameworks más potentes como Semantic Kernel.
Y muy bueno el recopilatorio del equipo de Visual Studio sobre novedades destacables que se introdujeron en el producto durante 2024. Si usáis a diario esta herramienta, echadle un ojo porque hay cosas muy interesantes.
Espero que os sean de utilidad 🙂
Por si te lo perdiste...
- Comprimir el resultado de acciones específicas en ASP.NET Core MVC
José M. Aguilar - Non-nullable property must contain a non-null value when exiting constructor: 7 formas de evitar el warning CS8618 en C#
José M. Aguilar
.NET Core / .NET
- The memory leak in ConcurrentQueue
Oren Eini - Measuring the impact of locks and waits on latency in your .NET apps
Christophe Nasarre - Stop the Leaks: Properly Disposing Objects in .NET
David McCarter - C# foreach: Definition and Best Practices
Stackify Team - Reading compilation options and the C# version in source generators
Andrew Lock - Local inter-process communication over named pipes with ASP.NET Core or StreamJsonRpc in .NET
Anthony Simmon - Comparing Records, Structs, and Classes in C#: When to Use What?
Ali Hamza Ansari - Enhance Your .NET HttpClient with HSTS Support
Gérald Barré - Introducing MSBuild.Sdk.SqlProj 3.0 - create, build, validate, analyze, pack and deploy SQL database projects with .NET 9
Erik Ejlskov Jensen - Mastering C# - Pattern Matching
Jesse Liberty - The Transition of .NET FluentAssertions to Paid Software
Tomasz Sobczak - C# Enum: Definition and Best Practices
Stackify Team - Working with JsonSerializerContext in System.Text.Json and Refit
Tomasz Cielecki

Tras el parón navideño, volvemos a la carga con la primera recopilación de 2025 🙂
Bueno, la frase anterior no es del todo cierta. Por una parte, aunque haya dejado de publicar durante un par de semanas, no he dejado de recopilar enlaces, así que esta edición es especialmente extensa: más de 90 enlaces. Y por otra parte, en realidad sería la segunda recopilación, si contamos la revisión de los contenidos más vistos del blog durante el pasado año que publiqué ayer 😊
Pero bueno, al tema...
Es difícil destacar algo en concreto ante tanto contenido, pero quizás me quedo con el post "The Myth of Perfect Code: Why It’s Hurting You More Than Helping", donde Terrance Craddock reflexiona sobre lo que deberíamos considerar "código perfecto".
También me voy a quedar con algo que, por diferente, me ha llamado la atención: "Unique Solving Method for Rubik's Cube", un método para resolver el cubo de Rubik presentado de forma muy visual. Si sois de los que en los 80 pasasteis horas intentando resolverlo, seguro que como mínimo os resultará curioso 🙂
Por si te lo perdiste...
- Este código C# no compila. ¿Cómo lo hacemos funcionar sin tocarlo?
José M. Aguilar - Crear desplegables desde enums en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- Critical: .NET Install links are changing
Richard Lander - Scheduling Background Jobs With Quartz in .NET (advanced concepts)
Milan Jovanović - Fast build and high security in .NET with Package Source Mapping
Tomasz Sobczak - Back to Basics: Using the Parallel Library to Massively Boost Loop Performance
Rick Strahl - Logging in .NET: Best Practices and Why You Should Love It
Marius Schröder - 10 Reasons to Upgrade to .NET 9
Anton Martyniuk - Vogen: turn your primitives (ints, decimals etc.) into value objects that represent domain concepts
Steve Dunn - StackOverflowException vs. OutOfMemoryException
Sergey Teplyakov - Static Lambda in C# 12 : Performance Improvement
Devesh Omar - C# Null-Conditional (?.) & Null-Coalescing (??) Operators Explained
Ivan Kahl - Automatically format your dotnet code using dotnet format
Josef Ottosson - Think Beyond Synchronous: The Ultimate Guide to Tasks in C#
Chris Woodruff - Moq Unit Testing in .NET Core with xUnit
Jaimin Shethiya - Implementing an interceptor with a source generator
Andrew Lock - Writing a String Numeric Comparer with .NET 9
Khalid Abuhakmeh - .NET 9 upgrade - notnull constraint
Bart Wullems - Exploring CollectionsMarshal for Dictionary
Gérald Barré - C# 12.0: collection expressions
Ian Griffiths - Writing a .NET profiler in C#
Kevin Gosse - Modern C# Part 3 – Switch Expressions
Jesse Liberty

Pues sí, se acabaron las fiestas y aquí estamos de nuevo, volviendo a la rutina. Con el 2025 recién estrenado, ante todo, me gustaría aprovechar la ocasión para desearos que sea un gran año en todos los sentidos🙂
Y para empezar con buen pie, vamos a seguir la tradición de aprovechar este primer post para hacer un breve recopilatorio de los artículos más leídos el año anterior, con idea de que podáis descubrir contenidos que quizás os habíais perdido, reencontraros con algo que os interesó en su momento, o simplemente ver qué contenidos están llamando más la atención al resto de lectores del blog.
Top 10 posts 2024 en Variable Not Found
En décimo lugar, inaugurando el top ten de 2024 tenemos una llamada de atención: el artículo "¡No uses ContainsKey() en un diccionario .NET para ver si existe un elemento antes de obtenerlo!" muestra el impacto en el rendimiento de la doble búsqueda (una para ver si existe el elemento y otra para obtenerlo) y cómo podemos solucionarlo fácilmente con las herramientas que proporciona el propio framework.
Seguidamente, en el noveno puesto de la lista, respondemos a una pregunta bastante habitual cuando empezamos con ASP.NET Core: ¿por qué mi aplicación no arranca? En el artículo "No se puede conectar al servidor web 'https', el servidor web ya no funciona y otras pistas de que no has lanzado correctamente tu aplicación ASP.NET Core", además de la respuesta, veremos otros síntomas que nos pueden ayudar a identificar el problema. Spoiler: has olvidado incluir el app.Run()
al final del código de inicialización 😉