在 Blazor 服务器端使用 CancellationTokenSource 去抖实现
Debounce implementation with CancellationTokenSource in Blazor server side
我在 Blazor 服务器端应用程序 (.net core 3.0) 中使用 CancellationTokenSource 实现了输入去抖。
它与预期的输入延迟配合得很好,但总是在调试输出中写入错误,
输入时:
Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Components.dll
快速打字时:
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
您有解决方法吗?
您可以在此处找到实现:
https://blazorfiddle.com/s/ij9l55ne
主页:
@page "/"
@using System.Threading
@using System.Threading.Tasks
<MyChildComponent OnTyping="async e => await OnTypingAsync(e)"/>
<div>@result</div>
@code {
string result;
public async Task OnTypingAsync(string myText)
{
await Task.Delay(1);//call GetDataAsync(myText) method
result = myText;
await InvokeAsync(StateHasChanged);
}
}
子组件:
@using System.Threading
@using System.Threading.Tasks
<input type="text" @oninput="async e => await OnInput(e)" />
@code {
[Parameter] public EventCallback<string> OnTyping { get; set; }
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct;
public async Task OnInput(ChangeEventArgs e)
{
Cts.Cancel();
Cts = new CancellationTokenSource();
Ct = Cts.Token;
await Task.Delay(500, Ct).ContinueWith(async task =>
{
if (!task.IsCanceled) {
await OnTyping.InvokeAsync(e.Value.ToString());
}
}, Ct);
}
}
javiercn 在我注册的 github issue 上提供了如何解决这个问题的好主意:
https://github.com/aspnet/AspNetCore/issues/16524#issuecomment-546847682
- 您需要在使用取消令牌时始终捕获 OperationCanceledException。
- 您应该避免在您的方法中使用 continue with,因为您没有捕获 SynchronizationContext,当您尝试从延续回调中更新 UI 时会产生错误。
我在 Blazor 服务器端应用程序 (.net core 3.0) 中使用 CancellationTokenSource 实现了输入去抖。
它与预期的输入延迟配合得很好,但总是在调试输出中写入错误, 输入时:
Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Components.dll
快速打字时:
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
您有解决方法吗?
您可以在此处找到实现: https://blazorfiddle.com/s/ij9l55ne
主页:
@page "/"
@using System.Threading
@using System.Threading.Tasks
<MyChildComponent OnTyping="async e => await OnTypingAsync(e)"/>
<div>@result</div>
@code {
string result;
public async Task OnTypingAsync(string myText)
{
await Task.Delay(1);//call GetDataAsync(myText) method
result = myText;
await InvokeAsync(StateHasChanged);
}
}
子组件:
@using System.Threading
@using System.Threading.Tasks
<input type="text" @oninput="async e => await OnInput(e)" />
@code {
[Parameter] public EventCallback<string> OnTyping { get; set; }
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct;
public async Task OnInput(ChangeEventArgs e)
{
Cts.Cancel();
Cts = new CancellationTokenSource();
Ct = Cts.Token;
await Task.Delay(500, Ct).ContinueWith(async task =>
{
if (!task.IsCanceled) {
await OnTyping.InvokeAsync(e.Value.ToString());
}
}, Ct);
}
}
javiercn 在我注册的 github issue 上提供了如何解决这个问题的好主意: https://github.com/aspnet/AspNetCore/issues/16524#issuecomment-546847682
- 您需要在使用取消令牌时始终捕获 OperationCanceledException。
- 您应该避免在您的方法中使用 continue with,因为您没有捕获 SynchronizationContext,当您尝试从延续回调中更新 UI 时会产生错误。