目录
- 写在前面
- 代码实现
- 调用示例
写在前面
Microsoft.Extensions.ObjectPool 是 ASP.NET Core 基础结构的一部分,当对象的初始化成本较高,并且可能被频繁使用时,才适合采用对象池技术;被ObjectPool管理的对象不会进入垃圾回收,使用时通过由实例对象实现的Get()方法,从对象池中借出对象,用完之后调用Return(T obj)方法,将对象还回去。也可以在Return(T obj)方法中设置判断条件,仅允许特定的对象进入对象池。
通过NuGet 获取 Microsoft.Extensions.ObjectPool 类库
代码实现
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using System.Security.Cryptography;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// DefaultPooledObjectPolicy: 默认的策略,继承抽象类PooledObjectPolicy
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);
});
builder.Services.TryAddSingleton<ObjectPool<Person>>(serviceProvider => {
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new PersonPoolPolicy();
return provider.Create(policy);
});
builder.Services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new StringBuilderPooledObjectPolicy();
return provider.Create(policy);
});
var app = builder.Build();
// config middleware
app.UseMiddleware<BirthdayMiddleware>();
app.MapGet(\”/\”, () => \”Hello rjcql!\”);
// return the SHA256 hash of a word
http://localhost:5128/hash/xxxx
app.MapGet(\”/hash/{word}\”, (string word, ObjectPool<ReusableBuffer> bufferPool) =>
{
var buffer = bufferPool.Get();
try
{
// Set the buffer data to the ASCII values of a word
for (var i = 0; i < word.Length; i++)
{
buffer.Data[i] = (byte)word[i];
}
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(buffer.Data.AsSpan(0, word.Length), hash);
return \”Hash: \” + Convert.ToHexString(hash);
}
finally
{
// Data is automatically reset because this type implemented IResettable
bufferPool.Return(buffer);
}
});
app.MapGet(\”/create/{name}\”, (string name, ObjectPool<Person> personPool) =>
{
var person = personPool.Get();
try
{
person.Id = Guid.NewGuid().ToString(\”N\”);
var lastName = person.Name; // 这个是上一个对象的值
person.Name = name;
return $\”{person.Id}:{person.Name}, {lastName}\”;
}
finally
{
// 根据条件回收
personPool.Return(person);
}
});
app.Run();
public class ReusableBuffer : IResettable
{
public byte[] Data { get; } = new byte[1024 * 1024]; // 1 MB
public bool TryReset()
{
Array.Clear(Data);
return true;
}
}
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
}
public class PersonPoolPolicy : PooledObjectPolicy<Person>
{
public override Person Create()
{
return new Person { Id = \”\”, Name = \”rjcql\” };
}
public override bool Return(Person p)
{
if (p.Name != \”rjcql\”)
{
// 不允许其他名称的对象放入对象池
return false;
}
return true;
}
}
/// <summary>
/// 创建中间件
/// </summary>
public class BirthdayMiddleware
{
private readonly RequestDelegate _next;
public BirthdayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context, ObjectPool<StringBuilder> builderPool)
{
var stringBuilder = builderPool.Get();
try
{
stringBuilder.Append(\”Hi\”);
// 在中间干点啥别的
// await context.Response.WriteAsync(stringBuilder.ToString());
await _next.Invoke(context);
}
finally // 即使出错也要保证归还对象
{
builderPool.Return(stringBuilder);
}
}
}
调用示例
因为设置了回收条件,所以只有名字为rjcql的对象才会被回收,所以每次调用都先把rjcql对象取出。
到此这篇关于ASP.NET Core中的对象池化技术详解的文章就介绍到这了,更多相关.NET Core对象池内容请搜索悠久资源网以前的文章或继续浏览下面的相关文章希望大家以后多多支持悠久资源网!
您可能感兴趣的文章:
- .NET Core中如何实现或使用对象池?
- .NET Core对象池的应用:编程篇
- .NET Core对象池的应用:设计篇
- .NET Core对象池的应用:扩展篇
- .NET Core 中对象池 Object Pool的使用
- ASP.NETCore中的对象池介绍