一、观察下面的代码
private DotNetObjectReference<Counter>? _objRef = null;
private bool disposedValue = false;
private async Task SendToJavaScript2Async(MouseEventArgs e)
{
var moudle = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != moudle)
{
if (_objRef == null)
{
_objRef = DotNetObjectReference.Create(this);
}
await moudle.InvokeVoidAsync("SendToJavascript2Async", H1Element, _objRef);
}
}
_objRef 被传入到js模块里面去了,脱离了C#的垃圾回收机制,因此需要主动释放这个资源。
二、一般的套路
- 继承IDisposable接口
- 实现接口IDisposable里面的函数Dispose,但是函数Dispose并不写具体的释放操作,而是写一个调用virtual的Dispose的函数。目的是:如果子类再继承自己,子类可以重写这个虚函数,并释放子类,然后子类再调用父类的虚函数,这样实现彻底的释放资源。
三、Blazor的样例代码
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
namespace BlazorAppJavaScript.Components.Pages
{
public partial class Counter : IDisposable
{
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
//第一个是函数名称;第二个和第三个是参数
//await jsRuntime.InvokeVoidAsync("$.test1","1","2");
}
}
private async Task ChangeTitleAsync(MouseEventArgs e)
{
var moudle = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != moudle)
{
await moudle.InvokeVoidAsync("test2", "暴风影音");
// 这句话很关键,通知界面去更新变量的值(否则变量还是原来的0)
//await this.InvokeAsync(this.StateHasChanged);
}
}
private async Task CallAsyncFunction(MouseEventArgs e)
{
var moudle = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != moudle)
{
var rst = await moudle.InvokeAsync<bool>("getPageSizeAsync");
if (rst)
currentCount += 23;
else
currentCount += 3;
//按钮本身就会调用await this.InvokeAsync(this.StateHasChanged);
//这里不用调用,否则死锁
//await this.InvokeAsync(this.StateHasChanged);
}
}
private ElementReference H1Element { get; set; }
private async Task SendToJavaScriptAsync(MouseEventArgs e)
{
var moudle = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != moudle)
{
await moudle.InvokeVoidAsync("SendToJavascript", H1Element);
}
}
private DotNetObjectReference<Counter>? _objRef = null;
private bool disposedValue = false;
private async Task SendToJavaScript2Async(MouseEventArgs e)
{
var moudle = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != moudle)
{
if (_objRef == null)
{
_objRef = DotNetObjectReference.Create(this);
}
await moudle.InvokeVoidAsync("SendToJavascript2Async", H1Element, _objRef);
}
}
//
private async Task StaticAsync(MouseEventArgs e)
{
var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./Components/Pages/Counter.razor.js");
if (null != module)
{
await module.InvokeVoidAsync("StaticJavascriptAsync");
}
}
private static readonly int[] result = [1,2,3,4,5];
[JSInvokable("foo")]
public static Task<int[]> ReturnArray()
{
return Task.FromResult(result);
}
[JSInvokable]
public void Update()
{
this.currentCount += 100;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
if (this._objRef != null)
{
this._objRef.Dispose();
this._objRef = null;
}
}
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// 释放未托管的资源,如例如打开的文件句柄等
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
// 如果有非托管资源(如 IntPtr、原生库句柄等),才需要析构函数
// 例如:private IntPtr nativeHandle; // 非托管资源
// 在这种情况下,即使用户没有调用 Dispose(),GC 在回收对象时,也会通过析构函数调用 Dispose(false) 来释放非托管资源。
~Counter()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: false);
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}