Events Blazor:从服务发送到组件的事件为null
我有一个由Blazor组件和Worker服务组成的程序。我正在使用.NETCore3.1 我的代码是根据手册编写的 在我的员工服务部,我有: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) {
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个独立的服务安装。当然,上面的注释假设发生了这种情况。我能够通过创建一个不同的非托管服务来实现这一点,该服务被注入到它自己的组件中