Search code examples
c#apiexceptiontimerdispose

System.ObjectDisposedException


----- Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling---

Hi can any one help me to resolve this problem

public class RealTimeMessage : ControllerBase
{
    private IHubContext<MessageHub, IMessageHubClient> messageHub;
    private readonly JobbyContext _Context;
    private  TimerManager _timer;
    public RealTimeMessage(IHubContext<MessageHub, IMessageHubClient> _messageHub,JobbyContext C,TimerManager T)
    {
        messageHub = _messageHub;
        _Context = C;
        _timer = T;
    }

    [HttpGet]
    [Route("SendMessage")]
    public  async Task<IActionResult> SendRealTimeMessage()
    {

        if (!_timer.IsTimerStarted)
         await _timer.PrepareTimer( async()=>
            {
                var m = await _Context.message.ToListAsync(x=> x.IsRead==false);// **=> Error here**
                if (m.Count>0)
                {
                    await messageHub.Clients.All.SendMessageToUser(m);
                }
                

            });
        
        return Ok(new { Message = "Request Completed" });
        
    }
}

public class TimerManager
{
    private Timer? _timer;
    private AutoResetEvent? _autoResetEvent;
    private Func<Task>? _action;
    public DateTime TimerStarted { get; set; }
    public bool IsTimerStarted { get; set; }

    public   async Task PrepareTimer(Func<Task> action)
    {
        _action =  action;
        _autoResetEvent = new AutoResetEvent(false);
        _timer = new  Timer(Execute, _autoResetEvent, 1000, 3000);
        TimerStarted = DateTime.Now;
        IsTimerStarted = true;
       
    }

    public async void Execute(object? stateInfo)
    {
        await _action();

        if ((DateTime.Now - TimerStarted).TotalSeconds > 10000)
        {
            IsTimerStarted = false;
                _timer.Dispose();

            
        }
    }
}

Solution

  • I would recommend a significant change in how this works.

    • When a user opens the site for the first time, it fetches all their unread messages
    • Every time a message is sent, it is always broadcast via SignalR to the recipient

    If the recipient is connected, they will receive the message immediately via SignalR. If they are not connected, they will receive it when they open the site. This will drastically simplify the implementation, and will reduce load on the database.