I’m doing a patch to solve a progress bar issue in an application that is a bit mess-up. The cancel on the progress bar used to do a Thread.Abort on the thread doing the heavy work. I changed that to raising a cancel flag that I can check at strategic place in the thread.
Most of the time it works fine but once in a while the cancellation doesn’t work at all. I suppose I could do a Application.DoEvents before looking at the status of the flag (there is no risk of reentry) but I would like a more “clean” option.
I would appreciate if someone could provide me information to understand what exactly is going on and how this stuff works behind the scene. I would like to know how to deal with this issue without using the BackgroundWorker (like you would in .net 1.1) but I would also like to know if the BackgroundWorker solve that kind of problems and how it does it.
Edit: I’m taking notes of you suggestions and will try some tomorrow and report back. I used a volatile bool at first by I think I updated it to an automatic property and forgot about the volatile. Could the worker thread keeps looking for the cached value again and again? I don’t see how I could have a deathlock. The worker to check for the flag since I managed to break there with by placing a breakpoint on-the-fly. I always test with the same set of data and most of the time it cancels just fine. The only thing that change between tests is the moment I press cancel. So far, I only tested in debug, started from VS.
Edit 2: It turns out that my issue isn’t related to my flag or anything I added. It’s more of a WinForm issue. The program get to call a ShowDialog (and there is already another ShowDialog blocked). I cannot drag the form and it doesn’t refresh by itself. The cancel button on it doesn’t even works. Here is the call stack when I pause everything.
[Code externe]
Mrnf.Son.Commun.dll!Mrnf.Son.Commun.Messages.BarreProgressionBase.ShowDialog(System.Windows.Forms.IWin32Window fenetre = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 274 + 0xb octets C#
Mrnf.Son.Commun.dll!Mrnf.Son.Commun.Controleurs.Utils.AttendreFinTraitement(System.Windows.Forms.Form parent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}, Mrnf.Son.Commun.Messages.BarreProgressionBase progressionBase = {Mrnf.Son.Commun.Messages.BarreProgressionMessage}, System.Threading.Thread thread = {System.Threading.Thread}) Ligne 302 + 0xd octets C#
Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Persisteurs.Echanges.LecteurDBFGeneriqueCollection.Importer(System.Windows.Forms.Form parent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 95 + 0x1d octets C#
Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Persisteurs.Echanges.PersisteurModeleEchanges.Importer(Mrnf.Son.Affaires.Entites.Echanges.ModeleEchanges unModele = {Mrnf.Son.Presentation.Windows.Controleurs.Echanges.ModeleEchanges.ModeleEchangesGenerique}, System.Windows.Forms.Form formParent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 1880 + 0xd octets C#
Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Entites.Echanges.ModeleEchanges.Importer(System.Windows.Forms.Form formParent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 875 + 0x18 octets C#
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm.EffectuerImport(Mrnf.Son.Affaires.Entites.Echanges.IModeleEchanges modele = {Mrnf.Son.Presentation.Windows.Controleurs.Echanges.ModeleEchanges.ModeleEchangesGenerique}) Ligne 1429 + 0xc octets C#
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm._terminerBtn_Click(object sender = {Text = Impossible d'évaluer l'expression, car un frame natif se trouve en haut de la pile des appels.}, System.EventArgs e = {System.EventArgs}) Ligne 1334 + 0x1d octets C#
[Code externe]
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm.WndProc(ref System.Windows.Forms.Message m = {System.Windows.Forms.Message}) Ligne 1133 + 0xb octets C#
[Code externe]
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.Controleurs.Sondages.ActionsSondages.OnImporterSysExt() Ligne 1362 + 0x1f octets C#
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Sondages.UEExploitationVue._mniImporterSysExt_Click(object sender = {System.Windows.Forms.ToolStripMenuItem}, System.EventArgs e = {System.EventArgs}) Ligne 820 + 0x12 octets C#
[Code externe]
Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.Program.Main() Ligne 148 + 0x8 octets C#
[Code externe]
Edit 3: If I pass null to the ShowDialog it works fine (the UI doesn’t freeze, the cancel button works, it cancels fine). I don’t really understand the magic behind all this.
The other posts are probably on track as to why.
I like to use WaitHandles in conjunction with Thread.Join()/Thread.Abort() when I’m trying to kill a thread.
Probably good to figure out your original deadlock issue too though.