Events Blazor:从服务发送到组件的事件为null

Events Blazor:从服务发送到组件的事件为null,events,.net-core,service-worker,blazor,Events,.net Core,Service Worker,Blazor,我有一个由Blazor组件和Worker服务组成的程序。我正在使用.NETCore3.1 我的代码是根据手册编写的 在我的员工服务部,我有: public event Func<double, Task> Notify; public double Data{ get; set; } public async Task Update(double data) { if (Notify != null) {

我有一个由Blazor组件和Worker服务组成的程序。我正在使用.NETCore3.1

我的代码是根据手册编写的

在我的员工服务部,我有:

    public event Func<double, Task> Notify;
    public double Data{ get; set; }

    public async Task Update(double data)
    {
        if (Notify != null)
        {
            await Notify.Invoke(data).ConfigureAwait(false);
        }
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
             await Update(Data).ConfigureAwait(false);
             ...

             await Task.Delay(1000, stoppingToken).ConfigureAwait(false);
        }
    }
公共事件功能通知;
公共双精度数据{get;set;}
公共异步任务更新(双数据)
{
如果(通知!=null)
{
wait Notify.Invoke(数据).configurewait(false);
}
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
同时(!stoppingToken.IsCancellationRequested)
{
等待更新(数据)。配置等待(错误);
...
等待任务。延迟(1000,stoppingToken)。配置等待(false);
}
}
在我的Blazor组件中:

@using MyNamespace
@inject WorkerService MyService
@implements IDisposable

<div>@DataToDisplay</div>

@code {

    private double DataToDisplay{ get; set; }

    protected override void OnInitialized()
    {
        MyService.Notify += OnNotify;
    }

    public async Task OnNotify(double data)
    {
        await InvokeAsync(() =>
        {
            DataToDisplay= data;
            StateHasChanged();
        });
    }

    public void Dispose()
    {
        MyService.Notify -= OnNotify;
    }
}
@使用MyNamespace
@注入WorkerService MyService
@实现IDisposable
@数据显示
@代码{
私有双数据显示{get;set;}
受保护的覆盖无效OnInitialized()
{
MyService.Notify+=OnNotify;
}
公共异步任务OnNotify(双数据)
{
等待调用同步(()=>
{
DataToDisplay=数据;
StateHasChanged();
});
}
公共空间处置()
{
MyService.Notify-=OnNotify;
}
}
调试后,我通知,Notify事件正确地连接到Blazor组件中的OnInitialized()方法中(我也尝试了使用
OnInitializedAsync()
的版本),但是,每次服务调用
Update()
方法时,在条件检查期间:
如果(Notify!=null)
,通知为null

我找不到原因。谢谢你的建议

public class InjectableService
    {
        public double Value { get; set; }
        public event Func<Task> Notify;
        public double Data { get; set; }

        public  async Task RefreshAsync(double value)
        {
            if (Notify is { })
            {
                Value = value;
                await Notify.Invoke();
            }
        }
@injectinjectableservice MyService
@实现IDisposable
@MyService.Value

@代码{ 受保护的覆盖无效OnInitialized() { MyService.Notify+=OnNotify; } 公共异步任务OnNotify() { 等待调用同步(()=> { StateHasChanged(); }); } 公共空间处置() { MyService.Notify-=OnNotify; } }
在Startup.cs中:

services.AddHostedService<MyService>();
services.AddSingleton<InjectableService>();
services.AddHostedService();
services.AddSingleton();
@injectinjectableservice MyService
@实现IDisposable
@MyService.Value

@代码{ 受保护的覆盖无效OnInitialized() { MyService.Notify+=OnNotify; } 公共异步任务OnNotify() { 等待调用同步(()=> { StateHasChanged(); }); } 公共空间处置() { MyService.Notify-=OnNotify; } }
在Startup.cs中:

services.AddHostedService<MyService>();
services.AddSingleton<InjectableService>();
services.AddHostedService();
services.AddSingleton();

基于对github的讨论: 我知道自.NETCore2.1以来,托管服务是暂时的

但是,有可能将其用作API,该线程底部描述了:

在Startup.cs中的
配置服务(iSeries收集服务)

services.AddSingleton();
services.AddSingleton(p=>p.GetService());

这显然很有魅力。

基于对github的讨论: 我知道自.NETCore2.1以来,托管服务是暂时的

但是,有可能将其用作API,该线程底部描述了:

在Startup.cs中的
配置服务(iSeries收集服务)

services.AddSingleton();
services.AddSingleton(p=>p.GetService());

这显然很有魅力。

我遇到了一个类似于你的问题,因为我想通过使用事件更新UI中的一些元素

查看服务注册方法,从Microsoft官方文档,
services.AddSingleton()
这是一条路,因为它允许多个实现

我所要做的就是创建一个带有接口的类:

public interface INotifierService
{
    // In an Interface, its all Public!


    delegate void UiChangedEventHandler(object source, EventArgs args);

    event UiChangedEventHandler UiChanged; //Handler


}
public class NotifierService:INotifierService
{

    public event INotifierService.UiChangedEventHandler UiChanged; //Event from the base Interface

    protected virtual void OnUiChanged()
    {
        UiChanged?.Invoke(this, EventArgs.Empty);
    }

}
以及从该接口派生的另一个类:

public interface INotifierService
{
    // In an Interface, its all Public!


    delegate void UiChangedEventHandler(object source, EventArgs args);

    event UiChangedEventHandler UiChanged; //Handler


}
public class NotifierService:INotifierService
{

    public event INotifierService.UiChangedEventHandler UiChanged; //Event from the base Interface

    protected virtual void OnUiChanged()
    {
        UiChanged?.Invoke(this, EventArgs.Empty);
    }

}
并在
Startup.cs:

        services.AddSingleton<Services.INotifierService, Services.NotifierService>();
services.AddSingleton();
而且效果很好


当然,别忘了将接口注入.razor文件并订阅它的事件

我遇到了一个类似于您的问题,因为我想使用事件更新UI中的一些元素

查看服务注册方法,从Microsoft官方文档,
services.AddSingleton()
这是一条路,因为它允许多个实现

我所要做的就是创建一个带有接口的类:

public interface INotifierService
{
    // In an Interface, its all Public!


    delegate void UiChangedEventHandler(object source, EventArgs args);

    event UiChangedEventHandler UiChanged; //Handler


}
public class NotifierService:INotifierService
{

    public event INotifierService.UiChangedEventHandler UiChanged; //Event from the base Interface

    protected virtual void OnUiChanged()
    {
        UiChanged?.Invoke(this, EventArgs.Empty);
    }

}
以及从该接口派生的另一个类:

public interface INotifierService
{
    // In an Interface, its all Public!


    delegate void UiChangedEventHandler(object source, EventArgs args);

    event UiChangedEventHandler UiChanged; //Handler


}
public class NotifierService:INotifierService
{

    public event INotifierService.UiChangedEventHandler UiChanged; //Event from the base Interface

    protected virtual void OnUiChanged()
    {
        UiChanged?.Invoke(this, EventArgs.Empty);
    }

}
并在
Startup.cs:

        services.AddSingleton<Services.INotifierService, Services.NotifierService>();
services.AddSingleton();
而且效果很好


当然,别忘了将接口注入.razor文件并订阅它的事件

出于兴趣,您的依赖注入看起来像什么?我的服务是单身吗?是的。Startup.cs包含如下内容:
services.AddSingleton()谁发起服务?我想是打电话给ExecuteAsync吧?在不使用ConfigureWait的情况下尝试您的代码…问题可能就在这里。你永远不会知道…这不是配置等待。我用两种方法尝试了上面的代码。首先,我没有将该服务实现为托管服务。我添加了一个按钮来启动ExecuteAsync方法。用户界面得到了预期的更新。我将服务实现更改为托管服务,因此需要将DI注册更改为
AddHostedService
。这导致了一个错误,表明服务未添加到DI,组件无法注入它。还添加了一个单音。没有错误,但UI未更新,通知为空。实际上,这样您就有了2个独立的服务安装。当然,上面的注释假设发生了这种情况。我能够通过创建一个不同的非托管服务来实现这一点,该服务被注入到它自己的组件中