[C#]Threads

Pagina: 1
Acties:
  • 589 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 22:04
threads zijn nieuw voor mij, nu probeer ik dit onderwerp mij eigen te maken. Ik heb al heel wat zitten doorlezen maar kan sommige dingen niet goed begrijpen.
Er wordt steeds aangehaald dat de main UI controls niet kunnen worden geupdate vanuit een andere opgestarte thread. En dit steeds dmv delegate/invoke moet gebeuren.
Dit laatste begrijp ik niet echt aangezien wanneer ik onderstaande code run wel gewoon de main UI kan updaten ?
Of is het principieel fout om een instantie van de main Form door te geven aan een opgestarte sub-thread?
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
namespace ThreadTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            MyClass myclass = new MyClass(this);

            ThreadStart job = new ThreadStart(myclass.ThreadJob);
            Thread thread = new Thread(job);
            thread.Start();
        }

        public void UpdateLabel(int i)
        {
            label1.Text = i.ToString();
        }
    }

    public class MyClass
    {
        private Form1 m_mainForm;

        public MyClass(Form1 _mainFrom)
        {
            m_mainForm = _mainFrom;
        }

        public void ThreadJob()
        {
            for (int i = 0; i < 10; i++)
            {
                m_mainForm.UpdateLabel(i);
                Thread.Sleep(500);
            }
        }
    }
}

Acties:
  • 0 Henk 'm!

  • BM
  • Registratie: September 2001
  • Laatst online: 20:37

BM

Moderator Spielerij
Op deze manier moet de class welke je als thread draait alle methodes van je mainform kennen. Mocht je je class ergens anders gaan gebruiken zal je daar als deze functies ook moeten gaan implementeren.

Als je events en invoke gebruikt kun je de class in het geheel loskoppelen van je applicatie, en deze zonder probs ergens anders gebruiken.

Ik ben geen threading expert, mochten er fouten inzitten laat maar weten ;)

Xbox
Even the dark has a silver lining | I'm all you can imagine times infinity, times three


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
jos707 schreef op maandag 28 januari 2008 @ 15:33:
threads zijn nieuw voor mij, nu probeer ik dit onderwerp mij eigen te maken. Ik heb al heel wat zitten doorlezen maar kan sommige dingen niet goed begrijpen.
Er wordt steeds aangehaald dat de main UI controls niet kunnen worden geupdate vanuit een andere opgestarte thread. En dit steeds dmv delegate/invoke moet gebeuren.
Als je gebruikt maakt van .NET 2.0 of hoger, kan je dat probleem 'abstraheren' door gebruik te maken van de BackGroundWorker.
Dit laatste begrijp ik niet echt aangezien wanneer ik onderstaande code run wel gewoon de main UI kan updaten ?
Of is het principieel fout om een instantie van de main Form door te geven aan een opgestarte sub-thread?
Uhm, ik zou dat niet doen. Meestal wil je je logica / taken die uitgevoerd worden gescheiden houden van je UI.
Je kan ook eens kijken naar de implementatie van de BackGroundWorker class zodat je dat invoken begrijpt.
Je kan ook eens deze topics doornemen:
[C#] button.Show() vanuit anderen Thread"
\[C#] Invoke naar UI Thread

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 22:04
Bedankt voor de snelle antwoorden!
Maar stel dat ik in het bovenstaande voorbeeld MyClass integreer in de hoofdklasse(Form1) dan gaat wordt argument 'logica/taken gescheiden' houden teniet gedaan. Maar de hoofdvraag blijft wel bestaan nl. waarom ik de main UI thread kan updaten vanuit een sub-thread zonder een invoke te gebruiken?
Of moet ik er vanuit gaan dat dit altijd zal werken maar dat het 'not done' is omdat het niet threadsafe is?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
jos707 schreef op maandag 28 januari 2008 @ 15:52:
Maar de hoofdvraag blijft wel bestaan nl. waarom ik de main UI thread kan updaten vanuit een sub-thread zonder een invoke te gebruiken?
Of moet ik er vanuit gaan dat dit altijd zal werken maar dat het 'not done' is omdat het niet threadsafe is?
:?
Net zoals ik dacht, krijg je met je voorbeeldcode toch mooi een InvalidOperationException voor je kiezen hoor.
Afbeeldingslocatie: http://users.pandora.be/fgzone/pics/xthreadexc.PNG

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10-09 11:15
whoami schreef op maandag 28 januari 2008 @ 16:26:
[...]

:?
Net zoals ik dacht, krijg je met je voorbeeldcode toch mooi een InvalidOperationException voor je kiezen hoor.
[afbeelding]
Zover ik zelf meegemaakt heb wordt dit sinds VS2005/.NET 2.0 strenger aangepakt door de CLR. Tenminste, zolang je in debug mode draait. Want mijn .NET 1.1 applicatie bleef op CLR2.0 wel gewoon draaien terwijl als ik het project opnieuw compileerde ik ook tegen die exception aanliep.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
In .NET 1.1 krijg je die exceptie idd niet, maar als ik naar de voorbeeldcode van de TS kijk, dan ben ik er zeker van dat hij geen gebruik maakt van .NET 1.1. :P

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Ik gebruik meestal ISynchronizeInvoke interface (deze is beschikbaar om Form en Control) om events te delegeren naar de handler in de juiste thread.

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 button1_onClick(object s, EventArgs e)
{
  ISynchronizeInvoke i = (ISynchronizeInvoke) this;

  if (i.InvokeRequired)
  {
      //this is a worker thread, call this event asynchroon
      EventHandler handlerDelegate = new EventHandler(button1_onClick);
  
      object[] args = new object { sender, e };

      //marshal data from worker thread to UI thread
      i.BeginInvoke(handlerDelegate , args);

      //do not process event
      return;
  }

  //remove the handler, you can only use it once
  button1.OnClick -= button1_onClick;

  //We're now in the UI thread, so here it's safe to update the GUI
  Text1.Text = "User clicked button!";
}


Deze methode is erg eenvoudig op alle UI events toe te passen. Veel events worden normaal niet threadsafe aangeroepen. Via deze methode gebruik je de synchronisatie context en een eenmalige asynchrone callback om de UI te updaten.

Deze methode stond ooit beschreven op de Best Practices sectie op msdn.microsoft.com. Kon zojuist helaas niet snel een link naar het oorspronkelijke artikel vinden.

Deze methode is ook enigsinds vergelijkbaar met het threadsafe doorlopen van een collectie (ICollection.SyncRoot).

Vergeet echter nooit dat threads een complex onderwerp zijn en blijven. Vooral synchroniseren van de verschillende processen is meestal lastig. Jammer genoeg worden UI events standaard niet via BeginInvoke aangeroepen. Want met threading komen meestal ook de onderwerpen zoals locking en atomic operations. Ook is het meestal verstandig enige kennis van transacties te hebben (System.Transaction namespace) zodat bij een exceptie een handeling kan worden terug gedraaid.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
Idd, die ISynchronizeInvoke interface gebruik ik ook.
Ik zie net dat, in m'n voorbeeld-code die in één van die gelinkte topics ik nog cast naar Windows.Forms.Control.
Even aanpassen. :P

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

whoami schreef op maandag 28 januari 2008 @ 16:34:
In .NET 1.1 krijg je die exceptie idd niet, maar als ik naar de voorbeeldcode van de TS kijk, dan ben ik er zeker van dat hij geen gebruik maakt van .NET 1.1. :P
Je kunt de detectie op een ontzettend smerige methode omzeilen door Control.CheckForIllegalCrossThreadCalls = false; te zetten in program.cs

Je hebt dan dezelfde werking als in .NET 1.x, alleen bestaat de kans dat niet alle events door de GUI ontvangen worden omdat ze op de verkeerde thread worden geraised.

Zie mijn eerdere post voor de door Microsoft aanbevolen afhandeling van UI threads.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10-09 11:15
Niemand_Anders schreef op maandag 28 januari 2008 @ 16:44:
[...]


Je kunt de detectie op een ontzettend smerige methode omzeilen door Control.CheckForIllegalCrossThreadCalls = false; te zetten in program.cs

Je hebt dan dezelfde werking als in .NET 1.x, alleen bestaat de kans dat niet alle events door de GUI ontvangen worden omdat ze op de verkeerde thread worden geraised.

Zie mijn eerdere post voor de door Microsoft aanbevolen afhandeling van UI threads.
Ik heb zoiets ook tijden terug een keer als voorbeeldje gedaan (maar dan niet asynchroon, nooit bij de voordelen stilgestaan), maar toen werd het hier afgedaan als bad omdat je dan dezelfde functie eigenlijk recursief aanroept wat nogal duister kan overkomen... Kan het topic niet meer terugvinden. Het enige wat ik nog iets anders zou doen is geen return in de if, maar de rest in een else plakken.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 22:04
whoami schreef op maandag 28 januari 2008 @ 16:26:
[...]

:?
Net zoals ik dacht, krijg je met je voorbeeldcode toch mooi een InvalidOperationException voor je kiezen hoor.
Goed, dat is duidelijk, ik had de code in 'release' mode gedraaid en kreeg deze exception niet te zien.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
Niemand_Anders schreef op maandag 28 januari 2008 @ 16:44:
[...]


Je kunt de detectie op een ontzettend smerige methode omzeilen door Control.CheckForIllegalCrossThreadCalls = false; te zetten in program.cs

Je hebt dan dezelfde werking als in .NET 1.x, alleen bestaat de kans dat niet alle events door de GUI ontvangen worden omdat ze op de verkeerde thread worden geraised.

Zie mijn eerdere post voor de door Microsoft aanbevolen afhandeling van UI threads.
Of je het nou zo doet, of gewoon de invocation list bekijkt, en voor iedere handler kijkt of er moet ge-invoked worden, dat maakt niet uit. Wat is het verschil ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • wboevink
  • Registratie: September 2004
  • Laatst online: 07-06 23:30

Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

whoami schreef op maandag 28 januari 2008 @ 17:14:
[...]
Of je het nou zo doet, of gewoon de invocation list bekijkt, en voor iedere handler kijkt of er moet ge-invoked worden, dat maakt niet uit. Wat is het verschil ?
Als je de CheckForIllegalCrossThreadCalls property op false zet staat de CLR toe dat een een UI element vanuit een andere thread aangeroepen mag worden zoals dit ook mogelijk was in .NET 1.x. Deze property is voornamelijk bedoeld als backwards compability.

Als je de property op false zet, hoef je niet meer de ISynchronizeInvoke interface te gebruiken om het event op de juiste thread uit te laten voeren. Echter zoals eerder aangegeven is dit erg af te raden omdat het dan mogelijk is dat een event niet op de juiste thread door de CLR wordt aangeroepen. Als het event op de verkeerde thread wordt afgehandeld, dan is de lijst met event listeners 'leeg' en wordt er dus niets met het event gedaan.

In sommige gevallen lijden tot een infinite loop, bijvoorbeeld als via een event een voortgangs percentage doorgegeven wordt en het programma sluit als '100' wordt terug gegeven. Uitgaand dat de code zelf correct is en uiteindelijk 100 als laatste waarde terug geeft, kan als de property CheckForIllegalCrossThreadCalls op false staat niet gegarandeerd wordt dat jouw event handler alle events door krijgt.

Daarom zijn het vanaf .NET 2.0 cross thread op UI elementen niet meer mogelijk. UI elementen zijn niet threadsafe. Met de ISynchronizeInvoke vang je gegarandeerd alle events af.

Cross threading programmeren is een van de lastigste gebieden om te beheersen. De CLR doet in principe alle resource management voor de applicatie, maar cross threading wordt nog steeds niet voor de programmeur afgehandeld, en dat is vreemd omdat de fouten welke hiermee kunnen optreden niet onderdoen aan buffer overruns of het aan aanroepen van een memory range welke al eerder is vrij gegeven.

Persoonlijk ben ik dus van mening dat de CLR het synchroniseren van events op meerdere threads standaard al correct behoort af te handelen.

Maar zolang dit bij de programmeur zelf wordt neergelegd is de ISynchronizeInvoke interface de enige veilige methode voor het afvangen van events op meerdere threads.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
Eh .... lees nu mijn post waar je op reageert nog eens.
Ik heb het helemaal niet over die CheckForIllegalCrossThreadCalls property, en ja, je moet -ook in .NET 1.1 - checken ivm x-threading issues ook al wordt daar geen exceptie gegooid.
Ik heb dat ook nergens anders ontkent; check m'n posthistory van de afgelopen paar jaar maar, dat verkondig ik al tijden.
Toch maar eerst eens lezen vooraleer je reageert ...

Ik had het erover dat jij jouw methode de 'beste' methode vind omdat ze 'aangeraden' wordt door MS, terwijl mijn methode insé gewoon net hetzelfde doet. (En leesbaarder imho :P).
jos707 schreef op maandag 28 januari 2008 @ 17:00:
[...]

Goed, dat is duidelijk, ik had de code in 'release' mode gedraaid en kreeg deze exception niet te zien.
Ik hoop dat je dat (builden in release mode) nu als oplossing gaat gebruiken, maar dat je jouw code daadwerkelijk gaat aanpassen. :)

[ Voor 23% gewijzigd door whoami op 29-01-2008 14:34 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

whoami schreef op dinsdag 29 januari 2008 @ 14:33:
Eh .... lees nu mijn post waar je op reageert nog eens.
Ik heb het helemaal niet over die CheckForIllegalCrossThreadCalls property, en ja, je moet -ook in .NET 1.1 - checken ivm x-threading issues ook al wordt daar geen exceptie gegooid.
Ik heb dat ook nergens anders ontkent; check m'n posthistory van de afgelopen paar jaar maar, dat verkondig ik al tijden.
Toch maar eerst eens lezen vooraleer je reageert ...
De quote haalde het stuk over de CheckForIllegalCrossThreadCalls aan. Vandaar mijn mis-interpretatie. Excuus ;-)

Overigens wil je niet weten hoeveel code ik heb gezien waarin de threads niet worden gesynchroniseerd. Bijna wekelijks wordt ik door een developer aan m'n jas getrokken omdat ze dus de cross thread exception krijgen, terwijl ze die niet in .NET 1.x kregen (conversie naar VS2008)

Wat betreft het controleren, dat blijft toch een raar gegeven wat eigenlijk gewoon door de CLR zelf al geregeld zou moeten worden. Dit valt bij mij onder de noemer resource management en Microsoft claimt dat de CLR dat voor jouw afhandeld (managed code).
Ik had het erover dat jij jouw methode de 'beste' methode vind omdat ze 'aangeraden' wordt door MS, terwijl mijn methode insé gewoon net hetzelfde doet. (En leesbaarder imho :P).
De (beste) methode betreft het gebruik van de ISynchronizeInvoke interface. Of die wordt toegepast bij het afvuren van het event of bij de afvang maakt niet zoveel uit, hoewel toepassing bij het afvuren wel gestructureerde overkomt. Zeker op het moment dat een event meerdere listeners heeft.

Ik noem altijd ook de mogelijkheid van CheckForIllegalCrossThreadCalls voor de volledigheid en dat het niet verstandig is deze te gebruiken. Developers moeten die keuze maken op basis van argumenten, niet omdat ik zeg dat het zo moet.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10-09 11:15
whoami schreef op dinsdag 29 januari 2008 @ 14:33:
Eh .... lees nu mijn post waar je op reageert nog eens.
Ik heb het helemaal niet over die CheckForIllegalCrossThreadCalls property, en ja, je moet -ook in .NET 1.1 - checken ivm x-threading issues ook al wordt daar geen exceptie gegooid.
Ik heb dat ook nergens anders ontkent; check m'n posthistory van de afgelopen paar jaar maar, dat verkondig ik al tijden.
Toch maar eerst eens lezen vooraleer je reageert ...

Ik had het erover dat jij jouw methode de 'beste' methode vind omdat ze 'aangeraden' wordt door MS, terwijl mijn methode insé gewoon net hetzelfde doet. (En leesbaarder imho :P).


[...]
Klein verschilletje is nog dat in jouw voorbeeld je 'm niet asynchroon uitvoert en Niemand_Anders wel. Kwam volgens mij ook het artikel tegen waar hij het uit heeft (msdn) en daarin werd ook aangehaald dat je dan tenminste ook niet blocking bent of zelfs cancellable acties kan gaan maken.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 22:04
whoami schreef op dinsdag 29 januari 2008 @ 14:33:
Ik hoop dat je dat (builden in release mode) nu als oplossing gaat gebruiken, maar dat je jouw code daadwerkelijk gaat aanpassen. :)
Nee, ik probeer het op een goede manier aan te passen natuurlijk O-)

Nu heb ik gemerkt dat het gebruik van een BackGroundWorker mij eigenlijk beter kan dienen. Bij het gebruik van een BGWorker mag je ook niet cross-thread controls aanpassen daarom probeer ik dit op te vangen dmv methodinvokers.
Alleen stuit ik hier op het probleem dat een methodinvoker geen parameters accepteerd. Ik probeer namelijk vanuit een sub-klasse een method aan te roepen dmv invoke in de hoofdklasse. Alleen zou ik graag een parameter mee willen geven.
Enige (betere) oplossing hiervoor of doe ik hier weer iets doms ?
Stukje code ter illustratie:
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
45
46
47
48
49
50
51
52
53
 public class CBackGroundWorker
    {
        static BackgroundWorker m_bw;
        private Form m_parentForm;
        private MethodInvoker m_invProgress;

        public CBackGroundWorker(MethodInvoker _invProgress, System.Windows.Forms.Form _parentForm)
        {
            m_parentForm = _parentForm;
            m_invProgress = _invProgress;

            m_bw = new BackgroundWorker();
            m_bw.WorkerReportsProgress = true;
            m_bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            m_bw.ProgressChanged += bw_ProgressChanged;
            m_bw.DoWork += bw_DoWork;

            m_bw.RunWorkerAsync("start");
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 100; i++)
            {
                if (m_bw.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                m_bw.ReportProgress(i);
                Thread.Sleep(1000);
            }
            e.Result = 123;    
        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine("Reached " + e.ProgressPercentage + "%");

            //m_invProgress zou een parameter moeten meekrijgen. v.b. m_invProgress(e.ProgressPercentage)         
            m_parentForm.BeginInvoke(m_invProgress); 
        }

        static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                Console.WriteLine("You cancelled!");
            else if (e.Error != null)
                Console.WriteLine("Worker exception: " + e.Error.ToString());
            else
                Console.WriteLine("Worker completed:" + e.Result);
        }
    }

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
Het voordeel van een backgroundworker is dat die zelf al gaat zorgen dat je eventhandlers op de juiste thread uitgevoerd worden.
Als je een BGW gebruikt, hoef je dat dus zelf niet meer te checken.
riezebosch schreef op dinsdag 29 januari 2008 @ 15:30:
[...]

Klein verschilletje is nog dat in jouw voorbeeld je 'm niet asynchroon uitvoert en Niemand_Anders wel. Kwam volgens mij ook het artikel tegen waar hij het uit heeft (msdn) en daarin werd ook aangehaald dat je dan tenminste ook niet blocking bent of zelfs cancellable acties kan gaan maken.
Eh, enlighten me.
Ik zie geen verschil, en ik kan ook cancellable acties maken ...

[ Voor 56% gewijzigd door whoami op 30-01-2008 16:40 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10-09 11:15
whoami schreef op woensdag 30 januari 2008 @ 16:39:
Het voordeel van een backgroundworker is dat die zelf al gaat zorgen dat je eventhandlers op de juiste thread uitgevoerd worden.
Als je een BGW gebruikt, hoef je dat dus zelf niet meer te checken.


[...]

Eh, enlighten me.
Ik zie geen verschil, en ik kan ook cancellable acties maken ...
ISynchronizeInvoke.Invoke versus ISynchronizeInvoke.BeginInvoke. Ik weet niet of dit het artikel is waar Niemand_Anders het over had, maar ik zag in de gauwigheid daar iets staan van "cancellation". Overigens moet moet ik wel zeggen dat ik het (gevoelsmatig) mooier vind om, zoals in jouw voorbeeld, het vanuit de thread te checken ipv in de GUI.

[ Voor 9% gewijzigd door riezebosch op 30-01-2008 17:18 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 22:04
whoami schreef op woensdag 30 januari 2008 @ 16:39:
Het voordeel van een backgroundworker is dat die zelf al gaat zorgen dat je eventhandlers op de juiste thread uitgevoerd worden.
Als je een BGW gebruikt, hoef je dat dus zelf niet meer te checken.
Sorry voor de kleine schop maar ik kom er niet echt uit. Ik begrijp niet goed wat je juist bedoelt met jouw antwoord.

Om de vraag anders te formuleren: ik wil een klasse BGworker kunnen aanroepen om een aantal copy-acties uit te voeren. Tijdens de copy-opdracht moet er een aantal controls worden geupdate in de aanroepende klasse. Telkens een instantie van de aanroepende klasse meegeven aan de BGworker-klasse is zowieso geen goed idee...dus vraag ik mij wat hiervoor de goede oplossing is? Gebruik van delegates lijkt mij ook niet echt de goede manier.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:56
Ik vermoed dat je de voortgang van je copy opdracht wilt laten zien aan de gebruiker ?
De BackGroundWorker heeft een event 'ProgressChanged' oid. Daar kan je een event-handler aan koppelen. Je kan zelf bepalen wanneer die event geraised moet worden, en de BGW zal er zelf voor zorgen dat je event-handler op de juiste thread (UI thread) uitgevoerd wordt.
To set up for a background operation, add an event handler for the DoWork event. Call your time-consuming operation in this event handler. To start the operation, call RunWorkerAsync. To receive notifications of progress updates, handle the ProgressChanged event. To receive a notification when the operation is completed, handle the RunWorkerCompleted event.

You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.

[ Voor 44% gewijzigd door whoami op 01-02-2008 17:24 ]

https://fgheysels.github.io/

Pagina: 1