C# Backgroundworker afsluiten

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo,

Heb een outlook vsto addin waarin meerdere backgroundworkers worden gebruikt. Heb wat problemen met het correct afsluiten van de backgroundworkers bij het sluiten van een formregion.

Na het sluiten van mijn formregion krijg ik “object reference not set” errors van code die afkomstig is uit de runworkercomplete (Datagrid bestaat niet meer). Ondanks dat ik hier tijdens runworkercomplete op controleer( zie voorbeeld) .
Ik geloof dat dit veroorzaakt wordt doordat CancelAsync(); de backgroundworker thread niet direct afsluit maar enkel een marker zet.
Ik zoek naar een goede manier om bij het sluiten van mijn formregion alle backgroundworkers netjes aftesluiten.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
 
if(!e.Cancelled)
 {
        List<ErpLibrary.Relatie> RLijst = (List<ErpLibrary.Relatie>)e.Result;
        if (this.InvokeRequired)
        {
               BeginInvoke(new MethodInvoker(delegate() { BindRelatie(RLijst); }));
        }
        else
        {
                BindRelatie(RLijst);
        }
 }

In het Do work event van mijn background worker zet ik de status op cancel als deze geannuleerd wordt.
C#:
1
2
3
4
5
 
 if (backgroundWorker.CancellationPending)
{
      e.Cancel = true;
}

In de oplossing van Matthew Watson
Uit de onderstaande post:
http://social.msdn.micros...0-4b2c-9363-89c46ec369df/

Zie je dat hij dit probleem heeft weten op te lossen door het sluiten van het form te annuleren en dit pas tijdens run workercompleet uitvoert. Deze oplossing ziet er mooi uit, echter ik heb te maken met een formregion. Hierbij heb je geen onclosing event en kan ik het sluiten hiervan ook niet annuleren.


Ik zag dat sommige mensen thread.sleep(200) gebruikten om backgroundworkers netjes te laten afsluiten. Maar de runworkercomplete zit in de zelfde thread als de sleep thread en wordt dus altijd daarna uitgevoerd. Hierdoor blijven background worker. Is busy en cancelation pending altijd tot het eind op true staan. Mis ik hier iets misschien?
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
private void FormRegionReadMail_FormRegionClosed(object sender, System.EventArgs e)
{        
       if (backgroundWorkerRelatiePerEmail.IsBusy)
       { backgroundWorkerRelatiePerEmail.CancelAsync(); }
            
       if (backgroundWorkerRelatieZoeken.IsBusy)
       { backgroundWorkerRelatieZoeken.CancelAsync(); }
       
       backgroundWorkerRelatiePerEmail.Dispose();
       backgroundWorkerRelatieZoeken.Dispose();
       
        int Teller = 0;
       while (Teller < 10)
       {
              if (!backgroundWorkerRelatieZoeken.CancellationPending &&                             !backgroundWorkerRelatiePerEmail.CancellationPending)
              {
                    break;
              }
              System.Diagnostics.Debug.Write("CancelPending: " + Teller.ToString());
              Teller = Teller + 1;
              Thread.Sleep(100);    
        }
}


Heeft iemand een suggestie hoe ik mijn formregion netjes kan afsluiten ?

[ Voor 6% gewijzigd door Verwijderd op 23-10-2009 14:20 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Psst; als je code post, gebruik dan even code tags a.u.b. Edit je bericht even dus ;) ( Afbeeldingslocatie: http://tweakimg.net/g/forum/images/icons/edit.gif )

[ Voor 29% gewijzigd door RobIII op 23-10-2009 13:55 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Waarom gebruik je Invoke in combinatie met BackgroundWorker? :? Kijk (nog) eens naar de help en het c# voorbeeld. ;)

Zolang er maar niks meer met het resultaat ervan wordt gedaan, lijkt het mij eigenlijk niet boeien of een BackgroundWorker al klaar is of niet (een beetje afhankelijk nog van bijv. locks op een filesystem natuurlijk).

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • urk_forever
  • Registratie: Juni 2001
  • Laatst online: 17-09 15:08
Volgens mij staan BGW's standaard ingesteld als niet annuleerbaar als je ze op een form zet. Heb je dat wel aangepast zodat ze wel annuleerbaar zijn?

Daarnaast doe je in je afsluit code van je form een CancelAsync, vervolgens een Dispose en dan ga je nog properties van je BGW uitlezen. Volgens mij gaat dat nooit goed! Die dispose zou je pas helemaal aan het einde van je code moeten doen.

Dit voorbeeld van de msdn site is een goed voorbeeld van hoe je de BGW zou moeten gebruiken. De this.backgroundWorker1.WorkerSupportsCancellation zorgt ervoor dat je kan annuleren.

In de DoWork functie wordt gecontroleerd of er geannuleerd is en stopt als dat het geval is.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public partial class Form1: Form
{
    public Form1()
    {
        InitializeComponent();
        this.backgroundWorker1.WorkerSupportsCancellation = true;
        this.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        this.backgroundWorker1.RunWorkerAsync();
    }

    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        for (;;)  // Simulate work.
        {
            System.Threading.Thread.Sleep(10000);

            if (this.backgroundWorker1.CancellationPending)
                break;
        }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (this.closePending)
        {
            this.closePending = false;
            this.Close();
        }
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (!this.closePending && this.backgroundWorker1.IsBusy)
        {
            this.backgroundWorker1.CancelAsync();
            this.Cursor = Cursors.WaitCursor;
            e.Cancel = true;
            this.closePending = true;
        }
    }

    private bool closePending;
}

Hail to the king baby!


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
urk_forever schreef op zaterdag 24 oktober 2009 @ 11:46:
Dit voorbeeld van de msdn site is een goed voorbeeld van hoe je de BGW zou moeten gebruiken.
Dat voorbeeld haalde TS ook aan. Ik vind het een slecht voorbeeld, want waarom zou je de user-interface laten wachten op een operatie die niet meer boeit? En bij de tweede keer klikken sluit je opeens wel?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor jullie antwoorden

De oplossing waarbij je het onclose event annuleert had ik inderdaad al gezien ( zie de link in mijn eerste post). Probleem is dat dit een outlook formregion is. Hierbij heb je geen onclosing event die het sluiten van de formregion kan annuleren.

Mijn background workers staan op supportcancelation true. En wanneer je de background workers annuleert met behulp van een button werkt dit ook prima.

De reden dat ik de invoke gebruik is dat de BindRelatie methode data in een datagrid zet. Als ik dat niet deed kreeg ik runtime crossthread errors.

De applicatie is een outlook vsto addin. Enkele gebruikers ervaren dat wanneer zij outlook afsluiten er nog enkele outlook processen in het taakbeheer blijven staan. Als je outlook dan opnieuw opstart start outlook niet totdat alle voorgaande processen worden afgesloten. Ik vermoed dat deze outlook processen ontstaan door niet correct afgesloten backgroundworkers. Via de msdn forums kreeg ik bevestigt dat niet afgesloten background worker niet automatisch worden opgeruimd dus vandaar dat ik hierna op zoek ben.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Verwijderd schreef op zaterdag 24 oktober 2009 @ 14:42:
De reden dat ik de invoke gebruik is dat de BindRelatie methode data in een datagrid zet. Als ik dat niet deed kreeg ik runtime crossthread errors.
Waarom zit je in RunWorkerCompleted dan alsnog de verkeerde Thread? Dit zou niet moeten, dat is juist het hele idee achter een BackgroundWorker. ;)
Via de msdn forums kreeg ik bevestigt dat niet afgesloten background worker niet automatisch worden opgeruimd dus vandaar dat ik hierna op zoek ben.
Dat is in ieder geval niet zo in het normale geval, want ze hebben IsBackground op True staan. Blijkbaar wacht er iets uit een Foreground thread? Waarom completen ze trouwens niet gewoon?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1