JsonSerializer.DeserializeAsync() randomly hangs indefinitely [Answered]
System.Text.Json
's DeserializeAsync
seems to (entirely at random) decide to hang indefinitely, throws no exceptions or anything in the process which is odd, it's always the same file in AppData
that causes it to hang.45 Replies
I know that it's not necessary to dispose of the filestream explicitly but I was trying anything to make sure it wasn't locking the file for whatever reason
unrelated, but you do not need to manually call filestream.DisposeAsync().
that is what that
await using
automatically does for you^^ ๐
yeah I had already typed it out ;p
what happens when you read the file in, and then deserialize it
also what explicit type are you passing it
would have to move to synchronous, if that's the move then I'll just make the whole thing synchronous and wrap it in a
Task.Run
I guess, as for the object it's just a POCO
nothing too wildwould have to move to synchronousno, what for
the async method doesn't have an overload for strings, only for streams
MemoryStream
that's true, didn't think of that
if it locks up when you read it into a MemoryStream, it might be a file problem
yeah
CopyToAsync
into a memorystream also causes a lockup
I switched file access just to be sure it wasn't trying to write for whatever reason as well, also a meaningless change
but yeah for some reason I'm having (seemingly entirely at random) a file issuewhat if you use File.OpenRead() instead of Open()?
as in
await using var stream = File.OpenRead(path);
interesting, I'm also experiencing a lockup on
filestream.DisposeAsync()
hereasync deadlock?
what kind of app is this
WPF
add
ConfigureAwait(false)
after all your callsuh this seems to have moved the deadlock somewhere else entirely, interesting
do I have to
ConfigureAwait(false)
everything?pretty much, yes
Unknown Userโข3y ago
Message Not Public
Sign In & Join Server To View
ConfigureAwait(TRUE)
is the default, which will try to run the continuation on the original threadI'm only using a single
GetAwaiter().GetResult()
call so I just need to make sure that the entire chain that comes from that has ConfigureAwait(false)
then?I have never had to use ConfigureAwait, I find it a bit sus. It'd just be moving the deadlock to another thread
everything else is
await
ed
it's really annoying that there's no way to really debug deadlocks, finding them when large parts of my codebase is async is a nightmareoh, well, I've never used GetAwaiter .GetResult either... why do you need that?
And also, not an answer to your question at all but... what's wrong with just File.ReadAllTextAsync ๐
Unknown Userโข3y ago
Message Not Public
Sign In & Join Server To View
registering the factory in the container for my global config which everything relies on has to be synchronous so I'm stuck with it unfortunately, I could maybe rethink my architecture and make that async but it'd be a big headache
okay, so the real reason why you're deadlocking is because the async library functions you're calling into are also using
ConfigureAwait(false)
which means the continuations can run on different threads. When you do GetResult() directly, you could potentially be doing that on the non-UI thread, which results in your deadlock
the solution is...
(drum roll please)as for this,
System.Text.Json
's async methods are for streams only, no stringsalso the fact that you now have to read the entire file at once, rather than letting the serializer read it as-needed
Unknown Userโข3y ago
Message Not Public
Sign In & Join Server To View
GitHub
AspNetCoreDiagnosticScenarios/AsyncGuidance.md at master ยท davidfow...
This repository has examples of broken patterns in ASP.NET Core applications - AspNetCoreDiagnosticScenarios/AsyncGuidance.md at master ยท davidfowl/AspNetCoreDiagnosticScenarios
read that part about deadlocks
lol, that's always the answer. Can we just remove Task.Result in the next version ๐
yeah I think I'll rethink my architecture a bit and allow for the global config to be loaded later on, that way I can use
async
properly and avoid constructorseither that^, or cheat and throw it into a Task.Run()
It's ugly but I would sort of recommend just, an async Initialize function where you need it
yeah that's (more or less) what I'm doing for a lot of other stuff already
but the global config is a bit sketchier, a fair bit of code is reliant on it being initialised when it's constructed, but I can just rework everything so it's more tolerant
handy to know that
GetAwaiter().GetResult()
can cause deadlocks though, was never really that aware of the inner workings, cheers allasync is nasty business
Unknown Userโข3y ago
Message Not Public
Sign In & Join Server To View
https://stackoverflow.com/questions/8145479/can-constructors-be-async the top answer here looks like a pretty neat solution, though IDK if it can be registered with DI like that
yeah the IoC container isn't hugely fond of basically any of the TPL, I'll just have to write it so the ViewModels can live without the config until I'm in an async context
โ
This post has been marked as answered!