从任意线程调用StateHasChanged()是否安全? [英] Is it safe to call StateHasChanged() from an arbitrary thread?
问题描述
从任意线程调用StateHasChanged()
是否安全?
Is it safe to call StateHasChanged()
from an arbitrary thread?
让我给您一些背景信息.想象一下您拥有的服务器端Blazor/Razor组件应用程序:
Let me give you some context. Imagine a Server-side Blazor/Razor Components application where you have:
- 单例服务
NewsProvider
,它从任意线程引发BreakingNews
事件. - 一个组件
News.cshtml
,该组件获取注入的服务并预订BreakingNews
事件.引发事件时,组件将更新模型并调用StateHashChanged()
- A singleton service
NewsProvider
that raisesBreakingNews
events from an arbitrary thread. - A component
News.cshtml
that gets the service injected and subscribes toBreakingNews
event. When the event is raised, the component updates the model and callsStateHashChanged()
using System;
using System.Threading;
namespace BlazorServer.App
{
public class BreakingNewsEventArgs: EventArgs
{
public readonly string News;
public BreakingNewsEventArgs(string news)
{
this.News = news;
}
}
public interface INewsProvider
{
event EventHandler<BreakingNewsEventArgs> BreakingNews;
}
public class NewsProvider : INewsProvider, IDisposable
{
private int n = 0;
public event EventHandler<BreakingNewsEventArgs> BreakingNews;
private Timer timer;
public NewsProvider()
{
timer = new Timer(BroadCastBreakingNews, null, 10, 2000);
}
void BroadCastBreakingNews(object state)
{
BreakingNews?.Invoke(this, new BreakingNewsEventArgs("Noticia " + ++n));
}
public void Dispose()
{
timer.Dispose();
}
}
}
News.cshtml
@page "/news"
@inject INewsProvider NewsProvider
@implements IDisposable
<h1>News</h1>
@foreach (var n in this.news)
{
<p>@n</p>
}
@functions {
EventHandler<BreakingNewsEventArgs> breakingNewsEventHandler;
List<string> news = new List<string>();
protected override void OnInit()
{
base.OnInit();
breakingNewsEventHandler = new EventHandler<BreakingNewsEventArgs>(OnBreakingNews);
this.NewsProvider.BreakingNews += breakingNewsEventHandler;
}
void OnBreakingNews(object sender, BreakingNewsEventArgs e)
{
this.news.Add(e.News);
StateHasChanged();
}
public void Dispose()
{
this.NewsProvider.BreakingNews -= breakingNewsEventHandler;
}
}
Startup.cs
using Microsoft.AspNetCore.Blazor.Builder;
using Microsoft.Extensions.DependencyInjection;
using BlazorServer.App.Services;
namespace BlazorServer.App
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Since Blazor is running on the server, we can use an application service
// to read the forecast data.
services.AddSingleton<WeatherForecastService>();
services.AddSingleton<INewsProvider, NewsProvider>();
}
public void Configure(IBlazorApplicationBuilder app)
{
app.AddComponent<App>("app");
}
}
}
它显然有效,但是我不知道StateHasChanged()
是否是线程安全的.如果不是,如何安全地呼叫StateHashChanged()
?是否有与Control.BeginInvoke
类似的东西?我应该使用SyncrhonizationContext.Post
吗?
it apparently works, but I don't know if StateHasChanged()
is thread safe. If it isn't, how can I call StateHashChanged()
safely?. Is there something similar to Control.BeginInvoke
? Should I use SyncrhonizationContext.Post
?
推荐答案
否,从任意线程调用StateHasChanged()
是不安全的.
No, calling StateHasChanged()
from an arbitrary thread is not safe.
The correct way to call StateHasChanged()
is by using InvokeAsync()
void OnBreakingNews(object sender, BreakingNewsEventArgs e)
{
InvokeAsync(() => {
news.Add(e.News);
StateHasChanged();
});
}
这篇关于从任意线程调用StateHasChanged()是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!