Blazor html5画布和c#计时器上的GC#U小问题
我想在htm5画布上实现圆形动画。我对blazor使用html5画布扩展。我做错了什么?在运行的blazor服务器上,在web assembly上,我在开发者工具中获得了GC_minor,我可以重现同样的问题:Blazor html5画布和c#计时器上的GC#U小问题,c#,asp.net-core,canvas,timer,blazor,C#,Asp.net Core,Canvas,Timer,Blazor,我想在htm5画布上实现圆形动画。我对blazor使用html5画布扩展。我做错了什么?在运行的blazor服务器上,在web assembly上,我在开发者工具中获得了GC_minor,我可以重现同样的问题: @的上述评论是正确的。您至少应该检查firstRender是否为true,并避免每次将draw()函数附加到新计时器 除此之外,您应该创建一个计时器,作为一个单独的字段。当组件被释放时,不要忘记释放定时器 最后,代码中还有另一个问题:您没有调用\u context.EndBatchAsy
firstRender
是否为true,并避免每次将draw()
函数附加到新计时器计时器
,作为一个单独的字段。当组件被释放时,不要忘记释放定时器
\u context.EndBatchAsync()
。因此,它不会绘制任何内容private Canvas2DContext _context;
protected BECanvasComponent _canvasReference;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
this._context = await this._canvasReference.CreateCanvas2DAsync();
var centerX = _canvasReference.Width / 2;
var centerY = _canvasReference.Height / 2;
var radius = 80;
var full = radius * 2;
var amount = 0.0;
var amountToIncrease = 0.1;
var aTimer = new Timer(500);
async void draw(Object source, ElapsedEventArgs e)
{
await this._context.BeginBatchAsync();
await this._context.ArcAsync(centerX, centerY, radius, 0, amount * Math.PI, false);
await this._context.SetFillStyleAsync("#13a8a4");
await this._context.FillAsync();
await this._context.SetLineWidthAsync(10);
await this._context.SetStrokeStyleAsync("#000000");
await this._context.StrokeAsync();
amount += amountToIncrease;
if (amount > full) amount = 0; // restart
await InvokeAsync(() =>
{
StateHasChanged();
});
}
aTimer.Elapsed += draw;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
[Demo2]:
顺便说一下,您不必通知此处的状态已更改(因为您没有更改组件状态):
这可能与这样的事实有关:如果(firstRender){您的代码应该在这里,并且只执行一次}否则,只要执行OnAfterRenderAsync,代码就会执行(super:)。我想知道为什么圆圈里有这些线?@MariusJurjonas我编辑了我的答案,告诉你原因以及如何避免这些线。请检查:) ... @implements IDisposable @* A Timer is a resource that should be disposed *@ ... @code{ private Canvas2DContext _context; protected BECanvasComponent _canvasReference; private Timer _aTimer = new Timer(500); public void Dispose() { this._aTimer.Dispose(); } protected override async Task OnAfterRenderAsync(bool firstRender) { this._context = await this._canvasReference.CreateCanvas2DAsync(); var centerX = _canvasReference.Width / 2; var centerY = _canvasReference.Height / 2; var radius = 80; var full = radius * 2; var amount = 0.0; var amountToIncrease = 0.1; if(firstRender) { // you might decide to put the above `var amount = 0.0; ...` here too, it depends on your needs this._aTimer.Elapsed += draw; this._aTimer.AutoReset = true; this._aTimer.Enabled = true; } async void draw(Object source, ElapsedEventArgs e) { await this._context.BeginBatchAsync(); await this._context.ArcAsync(centerX, centerY, radius, 0, amount * Math.PI, false); await this._context.SetFillStyleAsync("#13a8a4"); await this._context.FillAsync(); await this._context.SetLineWidthAsync(10); await this._context.SetStrokeStyleAsync("#000000"); await this._context.StrokeAsync(); await this._context.EndBatchAsync(); // add this line ! amount += amountToIncrease; if (amount > full) amount = 0; // restart await InvokeAsync(() => { StateHasChanged(); }); } } } await this._context.BeginBatchAsync(); await this._context.BeginPathAsync(); // add this line await this._context.ArcAsync(centerX, centerY, radius, 0, amount * Math.PI, false); ...
//await InvokeAsync(() => { StateHasChanged(); });