0

I'm using TCPClient to connect to device and get some data as a strings, then I'm trying to save data to DB and getting

"Cannot access a disposed object" error."

Maybe problem is because I'm trying to save to DB from async callback function? Please take a look, here are two functions: first one gets network stream, already connected to the device and starts reading data, second one is callback:

private void ReadDataAsync(NetworkStream nwStream)
        {
            byte[] buffer = new byte[1024];

            messageStream mStream = new messageStream(nwStream, buffer);

            if (nwStream.CanRead)
            {
                Console.WriteLine("Starting async");
                nwStream.BeginRead(buffer, 0, buffer.Length,
                    new AsyncCallback(OnReadEndAsync), mStream);
            }

            else
            {
                Console.WriteLine("Cannot read stream");
            }
        }

        private void OnReadEndAsync(IAsyncResult result)
        {
            String message = "";

            messageStream mStream = (messageStream)result.AsyncState;
            int incDataSize = mStream.nwStream.EndRead(result);

            message = Encoding.ASCII.GetString(mStream.buffer, 0, incDataSize);
            List<Event> events = new List<Event>();
            events = ProcessMessage(message);
            if(events.Any())
                 _repo.saveEventsToDB(events);
            if (mStream.nwStream.CanRead)
            {
                mStream.nwStream.BeginRead(mStream.buffer, 0, mStream.buffer.Length,
                    new AsyncCallback(OnReadEndAsync), mStream);
            }
        }
Vijunav Vastivch
  • 4,153
  • 1
  • 16
  • 30
  • None of this code shows the actual problem, your repository (*sigh*) has closed the context – TheGeneral Jan 04 '19 at 08:11
  • As written here, your method are not really "async". And your code is not usable as is. But yes, if they are called asynchronously and the _repo field is closed/disposed meanwhile, this is your error. My guess is you don't properly handle lifetime for your dbcontext. – AFract Jan 04 '19 at 08:11
  • find which line causes error. and write on here to get answer from ppl. – Arphile Jan 04 '19 at 08:12
  • Dig around in here `_repo.saveEventsToDB(events);` work out why you have closed and disposed the context (somwhere else), this will be your answer – TheGeneral Jan 04 '19 at 08:17
  • Thing is, if I call _repo.saveEventsToDB(events) from another place of program, for example, like this: [HttpPost("saveone")] public async Task saveOne(Event newEvent) { var events = new List(); events.Add(newEvent); await _repo.saveEventsToDB(events); return Ok(events); }' it works. So i think problem is because I call it from callback function.. Any idea what can I do? – Денис Пархоменко Jan 04 '19 at 10:31
  • Stop to access a disposed private field from a callback ? Stop to manage your connection with the same lifetime as the repository against good practices ? – AFract Jan 04 '19 at 11:06
  • @AFract could you please give an advice how to do it properly, or where to get an example? Thank you! – Денис Пархоменко Jan 06 '19 at 09:41

1 Answers1

0

Finally found a solution!

So problem was that I used DataContext dependancy, which was injected in the controller constructor - and it was disposed after HTTP request was completed.

So solution is to inject dependancy manually in the function itself, which needs access to the database:

  1. Inject scope factory IServiceScopeFactory scopeFactory in the controller constructor.

  2. Add this to my function where I need access to DBcontext:

    using (var scope = _scopeFactory.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); ... }