简体   繁体   English

SignalR:带计时器的 System.ObjectDisposedException

[英]SignalR: System.ObjectDisposedException with timer

I'm playing with signalR and I want to send every 2s a little message to my clients.我正在玩signalR,我想每2秒向我的客户发送一条小消息。 So I followed this tutorial , and it works good for chatting, now, I want to implement my timer.所以我跟着这个教程,它很适合聊天,现在,我想实现我的计时器。 Then, I made this ( ASP.NET .NET Core 3.1 ):然后,我做了这个( ASP.NET .NET Core 3.1 ):

public ChatHub()
{
    Debug.WriteLine("hello");
    var timer1 = new Timer();
    timer1.Elapsed += this.Timer1_Elapsed;
    timer1.Interval = 2000;
    timer1.Start();
}

private async void Timer1_Elapsed(object sender, ElapsedEventArgs e)
{
    Debug.WriteLine("tick");
    await SendMessage("user", "hello");
}

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user, message);
}

But everytime, I get this error (in this.Clients.Add... ):但每次,我都会收到此错误(在this.Clients.Add... 中):

System.ObjectDisposedException: Cannot access a disposed object. System.ObjectDisposedException:无法访问已处理的对象。

And I don't understand why, I checked stackoverflow, tried some solutions, but i'm already stuck.我不明白为什么,我检查了 stackoverflow,尝试了一些解决方案,但我已经被卡住了。

Thank for your help.感谢您的帮助。


Sample: https://github.com/Naografix/SignalRProblem示例: https : //github.com/Naografix/SignalRPproblem

Stacktrace:堆栈跟踪:

Message = "Cannot access a disposed object.\r\nObject name: 'HomeHub'."
at Microsoft.AspNetCore.SignalR.Hub.CheckDisposed()
at Microsoft.AspNetCore.SignalR.Hub.get_Clients()
at ****.HomeHub.<Timer1_Elapsed>d__1.MoveNext() in *****.Api\Hubs\HomeHub.cs:line 32

在此处输入图片说明

I can see here this:我可以在这里看到:

Don't store state in a property on the hub class.不要将状态存储在集线器类的属性中。 Every hub method call is executed on a new hub instance.每个集线器方法调用都在新的集线器实例上执行。

So I decided to search how to create a service for my hub.所以我决定搜索如何为我的集线器创建服务。 And this is what Medium does.这就是Medium所做的。 (Download their solution because lot of things are missing in their tutorial) (下载他们的解决方案,因为他们的教程中缺少很多东西)

Creating a timer in my hub was a bad approach .在我的集线器中创建计时器是一种糟糕的方法

Solved.解决了。

Another way to solve your problem is create a worker to tick every 2 seconds like following:解决问题的另一种方法是创建一个工作人员,每 2 秒打勾一次,如下所示:

On your ConfigureServices在您的ConfigureServices

services.AddHostedService<Worker>();

The worker class:工人阶级:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        await this.hub.Clients.All.SendAsync(broadcastMethodName, "Some message...");
        await Task.Delay(2000, stoppingToken);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM