Evenementer
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
Mat 4 Chance fir matzemaache kënnt Dir e Konferenz-Pak gewannen an op d’LIVE Grand Finale zu Las Vegas kommen
Méi gewuer ginnDëse Browser gëtt net méi ënnerstëtzt.
Upgrat op Microsoft Edge fir vun de Virdeeler vun leschten Eegeschaften, Sécherheetsupdaten, an techneschem Support ze profitéieren.
By Günther Foidl, Steve Gordon, and Samson Amaugo
Notiz
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Warnung
This version of ASP.NET Core is no longer supported. For more information, see the .NET and .NET Core Support Policy. For the current release, see the .NET 9 version of this article.
Wichteg
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
Microsoft.Extensions.ObjectPool is part of the ASP.NET Core infrastructure that supports keeping a group of objects in memory for reuse rather than allowing the objects to be garbage collected. All the static and instance methods in Microsoft.Extensions.ObjectPool
are thread-safe.
Apps might want to use the object pool if the objects that are being managed are:
For example, the ASP.NET Core framework uses the object pool in some places to reuse StringBuilder instances. StringBuilder
allocates and manages its own buffers to hold character data. ASP.NET Core regularly uses StringBuilder
to implement features, and reusing them provides a performance benefit.
Object pooling doesn't always improve performance:
Use object pooling only after collecting performance data using realistic scenarios for your app or library.
NOTE: The ObjectPool doesn't place a limit on the number of objects that it allocates, it places a limit on the number of objects it retains.
When DefaultObjectPoolProvider is used and T
implements IDisposable
:
NOTE: After the pool is disposed:
Get
throws an ObjectDisposedException
.Return
disposes the given item.Important ObjectPool
types and interfaces:
The ObjectPool can be used in an app in multiple ways:
ObjectPoolProvider<>
in DI and using it as a factory.Call Get to get an object and Return to return the object. There's no requirement to return every object. If an object isn't returned, it will be garbage collected.
The following code:
ObjectPoolProvider
to the Dependency injection (DI) container.IResettable
interface to automatically clear the contents of the buffer when returned to the object pool.using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using System.Security.Cryptography;
var builder = WebApplication.CreateBuilder(args);
builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
builder.Services.TryAddSingleton<ObjectPool<ReusableBuffer>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new DefaultPooledObjectPolicy<ReusableBuffer>();
return provider.Create(policy);
});
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
// return the SHA256 hash of a word
// https://localhost:7214/hash/SamsonAmaugo
app.MapGet("/hash/{name}", (string name, ObjectPool<ReusableBuffer> bufferPool) =>
{
var buffer = bufferPool.Get();
try
{
// Set the buffer data to the ASCII values of a word
for (var i = 0; i < name.Length; i++)
{
buffer.Data[i] = (byte)name[i];
}
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(buffer.Data.AsSpan(0, name.Length), hash);
return "Hash: " + Convert.ToHexString(hash);
}
finally
{
// Data is automatically reset because this type implemented IResettable
bufferPool.Return(buffer);
}
});
app.Run();
public class ReusableBuffer : IResettable
{
public byte[] Data { get; } = new byte[1024 * 1024]; // 1 MB
public bool TryReset()
{
Array.Clear(Data);
return true;
}
}
NOTE: When the pooled type T
doesn't implement IResettable
, then a custom PooledObjectPolicy<T>
can be used to reset the state of the objects before they are returned to the pool.
Microsoft.Extensions.ObjectPool is part of the ASP.NET Core infrastructure that supports keeping a group of objects in memory for reuse rather than allowing the objects to be garbage collected. All the static and instance methods in Microsoft.Extensions.ObjectPool
are thread-safe.
Apps might want to use the object pool if the objects that are being managed are:
For example, the ASP.NET Core framework uses the object pool in some places to reuse StringBuilder instances. StringBuilder
allocates and manages its own buffers to hold character data. ASP.NET Core regularly uses StringBuilder
to implement features, and reusing them provides a performance benefit.
Object pooling doesn't always improve performance:
Use object pooling only after collecting performance data using realistic scenarios for your app or library.
NOTE: The ObjectPool doesn't place a limit on the number of objects that it allocates, it places a limit on the number of objects it retains.
When DefaultObjectPoolProvider is used and T
implements IDisposable
:
NOTE: After the pool is disposed:
Get
throws an ObjectDisposedException
.Return
disposes the given item.Important ObjectPool
types and interfaces:
The ObjectPool can be used in an app in multiple ways:
ObjectPoolProvider<>
in DI and using it as a factory.Call Get to get an object and Return to return the object. There's no requirement that you return every object. If you don't return an object, it will be garbage collected.
The following code:
ObjectPoolProvider
to the Dependency injection (DI) container.ObjectPool<StringBuilder>
to the DI container.BirthdayMiddleware
.using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using ObjectPoolSample;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
builder.Services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new Microsoft.Extensions.ObjectPool.StringBuilderPooledObjectPolicy();
return provider.Create(policy);
});
builder.Services.AddWebEncoders();
var app = builder.Build();
// Test using /?firstname=Steve&lastName=Gordon&day=28&month=9
app.UseMiddleware<BirthdayMiddleware>();
app.MapGet("/", () => "Hello World!");
app.Run();
The following code implements BirthdayMiddleware
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.Extensions.ObjectPool;
namespace ObjectPoolSample;
public class BirthdayMiddleware
{
private readonly RequestDelegate _next;
public BirthdayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context,
ObjectPool<StringBuilder> builderPool)
{
if (context.Request.Query.TryGetValue("firstName", out var firstName) &&
context.Request.Query.TryGetValue("lastName", out var lastName) &&
context.Request.Query.TryGetValue("month", out var month) &&
context.Request.Query.TryGetValue("day", out var day) &&
int.TryParse(month, out var monthOfYear) &&
int.TryParse(day, out var dayOfMonth))
{
var now = DateTime.UtcNow; // Ignoring timezones.
// Request a StringBuilder from the pool.
var stringBuilder = builderPool.Get();
try
{
stringBuilder.Append("Hi ")
.Append(firstName).Append(" ").Append(lastName).Append(". ");
var encoder = context.RequestServices.GetRequiredService<HtmlEncoder>();
if (now.Day == dayOfMonth && now.Month == monthOfYear)
{
stringBuilder.Append("Happy birthday!!!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
else
{
var thisYearsBirthday = new DateTime(now.Year, monthOfYear,
dayOfMonth);
int daysUntilBirthday = thisYearsBirthday > now
? (thisYearsBirthday - now).Days
: (thisYearsBirthday.AddYears(1) - now).Days;
stringBuilder.Append("There are ")
.Append(daysUntilBirthday).Append(" days until your birthday!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
}
finally // Ensure this runs even if the main code throws.
{
// Return the StringBuilder to the pool.
builderPool.Return(stringBuilder);
}
return;
}
await _next(context);
}
}
Microsoft.Extensions.ObjectPool is part of the ASP.NET Core infrastructure that supports keeping a group of objects in memory for reuse rather than allowing the objects to be garbage collected.
You might want to use the object pool if the objects that are being managed are:
For example, the ASP.NET Core framework uses the object pool in some places to reuse StringBuilder instances. StringBuilder
allocates and manages its own buffers to hold character data. ASP.NET Core regularly uses StringBuilder
to implement features, and reusing them provides a performance benefit.
Object pooling doesn't always improve performance:
Use object pooling only after collecting performance data using realistic scenarios for your app or library.
WARNING: The ObjectPool
doesn't implement IDisposable
. We don't recommend using it with types that need disposal. ObjectPool
in ASP.NET Core 3.0 and later supports IDisposable
.
NOTE: The ObjectPool doesn't place a limit on the number of objects that it will allocate, it places a limit on the number of objects it will retain.
ObjectPool<T> - the basic object pool abstraction. Used to get and return objects.
PooledObjectPolicy<T> - implement this to customize how an object is created and how it is reset when returned to the pool. This can be passed into an object pool that you construct directly.... OR
Create acts as a factory for creating object pools.
The ObjectPool can be used in an app in multiple ways:
ObjectPoolProvider<>
in DI and using it as a factory.Call Get to get an object and Return to return the object. There's no requirement that you return every object. If you don't return an object, it will be garbage collected.
The following code:
ObjectPoolProvider
to the Dependency injection (DI) container.ObjectPool<StringBuilder>
to the DI container.BirthdayMiddleware
.public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new StringBuilderPooledObjectPolicy();
return provider.Create(policy);
});
services.AddWebEncoders();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Test using /?firstname=Steve&lastName=Gordon&day=28&month=9
app.UseMiddleware<BirthdayMiddleware>();
}
}
The following code implements BirthdayMiddleware
public class BirthdayMiddleware
{
private readonly RequestDelegate _next;
public BirthdayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context,
ObjectPool<StringBuilder> builderPool)
{
if (context.Request.Query.TryGetValue("firstName", out var firstName) &&
context.Request.Query.TryGetValue("lastName", out var lastName) &&
context.Request.Query.TryGetValue("month", out var month) &&
context.Request.Query.TryGetValue("day", out var day) &&
int.TryParse(month, out var monthOfYear) &&
int.TryParse(day, out var dayOfMonth))
{
var now = DateTime.UtcNow; // Ignoring timezones.
// Request a StringBuilder from the pool.
var stringBuilder = builderPool.Get();
try
{
stringBuilder.Append("Hi ")
.Append(firstName).Append(" ").Append(lastName).Append(". ");
var encoder = context.RequestServices.GetRequiredService<HtmlEncoder>();
if (now.Day == dayOfMonth && now.Month == monthOfYear)
{
stringBuilder.Append("Happy birthday!!!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
else
{
var thisYearsBirthday = new DateTime(now.Year, monthOfYear,
dayOfMonth);
int daysUntilBirthday = thisYearsBirthday > now
? (thisYearsBirthday - now).Days
: (thisYearsBirthday.AddYears(1) - now).Days;
stringBuilder.Append("There are ")
.Append(daysUntilBirthday).Append(" days until your birthday!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
}
finally // Ensure this runs even if the main code throws.
{
// Return the StringBuilder to the pool.
builderPool.Return(stringBuilder);
}
return;
}
await _next(context);
}
}
Feedback zu ASP.NET Core
ASP.NET Core ass en Open-Source-Projet. Wielt e Link, fir Feedback ze ginn:
Evenementer
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
Mat 4 Chance fir matzemaache kënnt Dir e Konferenz-Pak gewannen an op d’LIVE Grand Finale zu Las Vegas kommen
Méi gewuer ginn