C
C#2y ago
HimmDawg

❔ Deadlock with SynchonizationContext and locks?

I have quite a tricky problem fluffyFoxThink Our WinForms .NET Framework 4.8 program has a UI thread and a System.Timers.Timer. In the Elapsed event, I do some stuff that is dispatched to the UI thread via SynchronizationContext.Post(). https://paste.mod.gg/sbclvarnxuwv/0 PushNotification is a function that takes a NotificationPopup (simply a Form with some extras) and pushes it to a queue, which dequeues those Forms and shows them on screen. Just like a popup. If I don't use that Post() then the Forms have holes where the controls should be. https://paste.mod.gg/sbclvarnxuwv/1 Now the thing is, on other pcs, this can lead to an exception where the thread the context is from does no longer exist. A coworker inserted some locks, which didn't really help and I don't see any obvious problem. What I did so far was instead of getting the context inside of this class itself, I got it on the ui thread and injected it into the constructor. I know the code samples are a bit over the place, but this thing is quite massive, so if something is unclear, then I'll provide some mode code
8 Replies
sibber
sibber2y ago
doesn't the winforms timer automatically dispatch to the ui?
sibber
sibber2y ago
Timer Class (System.Windows.Forms)
Implements a timer that raises an event at user-defined intervals. This timer is optimized for use in Windows Forms applications and must be used in a window.
HimmDawg
HimmDawg2y ago
As the docs state: "Must be used in a window". The code where I'm using the timer isn't a window
D.Mentia
D.Mentia2y ago
IDK what SynchronizationContext.Post does, but you can just myForm.Invoke((MethodInvoker) delegate () => myForm.DoThing()) to get winforms to do things back on the UI thread
sibber
sibber2y ago
oh well i see youre passing the sync context but maybe it isnt the one you expect? id pass an Action<Action> that calls Form.Invoke since thats guaranteed to run on the ui thread
HimmDawg
HimmDawg2y ago
So the call stack up until the point of the above code is
Main()
L Method1()
L Method2()
L Method3()
L Method4()
Main()
L Method1()
L Method2()
L Method3()
L Method4()
No threads are being created in the meantime so I'm certain that the SynchronizationContext is actually the context of the UI thread. I think I tried using invoke before fluffyFoxThink not quite sure though. I'm gonna reevaluate this Yeah, I'll try that. SynchronizationContext.Post should dispatch the execution of a delegate to the thread the context is coming from. Every thread can have such a context.
D.Mentia
D.Mentia2y ago
Sounds dangerous, if they call ConfigureAwait(false) you're out of luck with that
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.