从任意线程调用StateHasChanged()是否安全? [英] Is it safe to call StateHasChanged() from an arbitrary thread?

查看:274
本文介绍了从任意线程调用StateHasChanged()是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从任意线程调用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 raises BreakingNews events from an arbitrary thread.
  • A component News.cshtml that gets the service injected and subscribes to BreakingNews event. When the event is raised, the component updates the model and calls StateHashChanged()
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.

调用StateHasChanged()的正确方法是使用

The correct way to call StateHasChanged() is by using InvokeAsync()

void OnBreakingNews(object sender, BreakingNewsEventArgs e)
{
    InvokeAsync(() => {
        news.Add(e.News);
        StateHasChanged();
    });
}

这篇关于从任意线程调用StateHasChanged()是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆