Javascript instance.invokeMethod内存泄漏
我通过.invokeMethod打了很多回C#的电话,我的垃圾收集器似乎被卡住了。显然,我不太了解Javascript/Blazor互操作内存管理,所以希望你们中的一位能够提供帮助 我正在设置window.requestAnimationFrame以调用c#。JS如下所示:Javascript instance.invokeMethod内存泄漏,javascript,visual-studio,blazor,Javascript,Visual Studio,Blazor,我通过.invokeMethod打了很多回C#的电话,我的垃圾收集器似乎被卡住了。显然,我不太了解Javascript/Blazor互操作内存管理,所以希望你们中的一位能够提供帮助 我正在设置window.requestAnimationFrame以调用c#。JS如下所示: <script type="text/javascript"> window.anim = { start: function (instance) { cons
<script type="text/javascript">
window.anim = {
start: function (instance) {
console.log('start');
return window.requestAnimationFrame(function (timestamp) { anim.callback(instance); });
},
callback: function (instance) {
instance.invokeMethod('IncrementCount');
var callbackId = window.requestAnimationFrame(function (timestamp) { anim.callback(instance); });
},
stop: function (callbackId) {
window.cancelAnimationFrame(callbackId);
}
};
</script>
@page "/counter"
@inject IJSRuntime JSRuntime;
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var dotNetReference = DotNetObjectReference.Create(this);
await JSRuntime.InvokeAsync<string>("window.anim.start", dotNetReference);
}
}
[JSInvokable("IncrementCount")]
public void IncrementCount()
{
currentCount++;
StateHasChanged();
}
}
window.anim={
开始:函数(实例){
console.log('start');
返回window.requestAnimationFrame(函数(时间戳){anim.callback(实例);});
},
回调:函数(实例){
invokeMethod('IncrementCount');
var callbackId=window.requestAnimationFrame(函数(时间戳){anim.callback(实例);});
},
停止:函数(回调ID){
window.cancelAnimationFrame(callbackId);
}
};
我的Razor页面如下所示:
<script type="text/javascript">
window.anim = {
start: function (instance) {
console.log('start');
return window.requestAnimationFrame(function (timestamp) { anim.callback(instance); });
},
callback: function (instance) {
instance.invokeMethod('IncrementCount');
var callbackId = window.requestAnimationFrame(function (timestamp) { anim.callback(instance); });
},
stop: function (callbackId) {
window.cancelAnimationFrame(callbackId);
}
};
</script>
@page "/counter"
@inject IJSRuntime JSRuntime;
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var dotNetReference = DotNetObjectReference.Create(this);
await JSRuntime.InvokeAsync<string>("window.anim.start", dotNetReference);
}
}
[JSInvokable("IncrementCount")]
public void IncrementCount()
{
currentCount++;
StateHasChanged();
}
}
@page”/counter
@注入IJSRuntime JSRuntime;
柜台
当前计数:@currentCount
点击我
@代码{
私有int currentCount=0;
AfterRenderAsync(bool firstRender)上受保护的重写异步任务
{
if(firstRender)
{
var dotNetReference=DotNetObjectReference.Create(此);
等待JSRuntime.InvokeAsync(“window.anim.start”,dotNetReference);
}
}
[JSInvokable(“IncrementCount”)]
公共无效增量计数()
{
currentCount++;
StateHasChanged();
}
}
我的垃圾收集器很快就会出现“GC_MINOR:(托儿所满)”消息,我的System/JSArrayBufferData看起来很大。
从文档中,我可以推断出应该处理对象,但它们也应该在这样的实例中处理吗?(在哪里?!)
(更新:好的,所以System/JSArrayBufferData总是很大,即使在运行Blazor示例时也是如此。所以我想这本身并没有任何迹象……但这仍然对我没有帮助)
这是一个问题的原因是,当我尝试做任何有意义的事情时,GC通常会立即启动。这里的例子只是为了说明即使在最简单的情况下也会发生这种情况
谢谢
/托马斯这可能不起作用,并被添加为对原始问题的评论的更完整的建议。我会鼓励OP评论这有多有效,也鼓励其他人纠正我的错误,以便我能了解更多 由于“IJSRuntime”填满了内存,其背后的思想是,运行时的生存期可能比它应该持续的时间长得多,而且由于Blazor是一个有状态的框架,因此状态也会随之产生 可以尝试使用
OwningComponentBase
将JS运行时的作用域强制到组件的生命周期、Blazor服务器中连接的生命周期或Blazor WASM中的单例。设置应该只需要几行代码。在Razor文件的顶部:
@继承OwningComponentBase
然后在@code块中:
@code{
//属性,而不是在此处注入
公共IJSRuntime运行时{get;set;}
//将运行时设置为作用域服务,因此它将发布并可用
//用于在拆下组件时进行垃圾收集
受保护的覆盖无效OnInitialized()
{
运行时=ScopedServices.GetRequiredService();
}
}
如果我的想法是正确的,这将有助于内存管理。我鼓励其他可能对这一主题更了解的人也评论或编辑这篇文章
以下是Blazor中关于作用域服务生命周期的说明
希望这有帮助,请回来报告 这可能不起作用,将作为对原始问题的评论的更完整建议添加。我会鼓励OP评论这有多有效,也鼓励其他人纠正我的错误,以便我能了解更多 由于“IJSRuntime”填满了内存,其背后的思想是,运行时的生存期可能比它应该持续的时间长得多,而且由于Blazor是一个有状态的框架,因此状态也会随之产生 可以尝试使用
OwningComponentBase
将JS运行时的作用域强制到组件的生命周期、Blazor服务器中连接的生命周期或Blazor WASM中的单例。设置应该只需要几行代码。在Razor文件的顶部:
@继承OwningComponentBase
然后在@code块中:
@code{
//属性,而不是在此处注入
公共IJSRuntime运行时{get;set;}
//将运行时设置为作用域服务,因此它将发布并可用
//用于在拆下组件时进行垃圾收集
受保护的覆盖无效OnInitialized()
{
运行时=ScopedServices.GetRequiredService();
}
}
如果我的想法是正确的,这将有助于内存管理。我鼓励其他可能对这一主题更了解的人也评论或编辑这篇文章
以下是Blazor中关于作用域服务生命周期的说明
希望这有帮助,请回来报告 所以,在进一步调查之后,我相当肯定我误解了Mono-GC消息的内存泄漏 看起来根本没有泄漏,但GC只是让您知道它正在清理。为这场白费力气的追逐道歉!:) 我仍然关心触发这篇文章()的项目中GC提供的信息量,但我将对此进行更多的研究
谢谢 所以,在进一步调查之后,我相当肯定我误解了Mono-GC消息的内存泄漏 看起来没有漏水