[.NET & Winforms] events handling probleem

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Hi allemaal :)

Ik heb het volgende probleem:

Ik heb een Excel bestand, met een taskpane (via Addin Express).

Dat taskpane is gewoon een usercontrol die geplaatst wordt in een container, en dan heb je toegang tot de excel applicatie. Heel eenvoudig dus.

Maar nu moet ik een checkbox schrijven die als die wordt gechecked een bepaald value naar de sheet moet schrijven. So far so good.

Het probleem is dat op het moment dat die value naar de sheet wordt geschreven dat er een calculatie wordt getriggerd.

Nu zou ik dus die checkbox willen disablen om te vermijden dat calculaties 'gequeued' kunnen worden.

Dus ik heb mijn CheckHandler

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
Private Sub CheckHandler(..., ...) handles CheckBoxTest.Checked

   Me.CheckBoxTest.Enabled = False

   Me.Update() 'update the UI

   'schrijf iets weg naar het field wat een calculation triggert.
   'dit duurt +- 5 seconden

   Me.CheckBoxTest.Enabled = True
End Sub


Goed dat werkt dus, maar een persoon kan nog altijd meerdere keren op de checkbox klikken, omdat het lijkt dat het niet werkt, maar dan worden zijn acties gewoon op een queue gezet door .NET en achter elkaar afgehandeld (frustratie!)

Nu had ik al geprobeert van een panel ervoor te tekenen (doorschijnend) of de gehele user control op disabled te zetten maar zelfs dat biedt geen soelaas.

Kent iemand hier de quirks van Winforms en zou die persoon mij kunnen uitleggen hoe ik dit probleem omzeil? :)

[ Voor 5% gewijzigd door Snake op 26-02-2010 14:09 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • lier
  • Registratie: Januari 2004
  • Laatst online: 22:13

lier

MikroTik nerd

Misschien kan je uitleggen waarom een gebruiker niet meerdere keren op de checkbox mag klikken ?
Kan je ook beter/goed uitleggen wat je bedoeld met het queuen ?

Is iets eenvoudigs als het tijdelijk loskoppelen van de events niet toereikend ?

Eerst het probleem, dan de oplossing


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
lier schreef op vrijdag 26 februari 2010 @ 13:56:
Misschien kan je uitleggen waarom een gebruiker niet meerdere keren op de checkbox mag klikken ?
Kan je ook beter/goed uitleggen wat je bedoeld met het queuen ?
Startpost beetje geupdated :)
3,000 gebruikers in de business leg je niets uit :P zij leggen mij uit wat ze willen en ik mag kruipen ;)
Is iets eenvoudigs als het tijdelijk loskoppelen van de events niet toereikend ?
Dat ik daar niet aan heb gedacht. Eens proberen!

Neen helaas, dat werkt niet.

[ Voor 6% gewijzigd door Snake op 26-02-2010 14:09 ]

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • urk_forever
  • Registratie: Juni 2001
  • Laatst online: 16:40
Snake schreef op vrijdag 26 februari 2010 @ 13:51:
Hi allemaal :)

Ik heb het volgende probleem:

Ik heb een Excel bestand, met een taskpane (via Addin Express).

Dat taskpane is gewoon een usercontrol die geplaatst wordt in een container, en dan heb je toegang tot de excel applicatie. Heel eenvoudig dus.

Maar nu moet ik een checkbox schrijven die als die wordt gechecked een bepaald value naar de sheet moet schrijven. So far so good.

Het probleem is dat op het moment dat die value naar de sheet wordt geschreven dat er een calculatie wordt getriggerd.

Nu zou ik dus die checkbox willen disablen om te vermijden dat calculaties 'gequeued' kunnen worden.

Dus ik heb mijn CheckHandler

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
Private Sub CheckHandler(..., ...) handles CheckBoxTest.Checked

   Me.CheckBoxTest.Enabled = False

   Me.Update() 'update the UI

   'schrijf iets weg naar het field wat een calculation triggert.
   'dit duurt +- 5 seconden

   Me.CheckBoxTest.Enabled = True
End Sub


Goed dat werkt dus, maar een persoon kan nog altijd meerdere keren op de checkbox klikken, omdat het lijkt dat het niet werkt, maar dan worden zijn acties gewoon op een queue gezet door .NET en achter elkaar afgehandeld (frustratie!)

Nu had ik al geprobeert van een panel ervoor te tekenen (doorschijnend) of de gehele user control op disabled te zetten maar zelfs dat biedt geen soelaas.

Kent iemand hier de quirks van Winforms en zou die persoon mij kunnen uitleggen hoe ik dit probleem omzeil? :)
Komt dit niet doordat je het wegschrijven en het wachten op het updaten van de berekening in je GUI thread doet? Doordat je GUI thread nu 5 sec's 'hangt' worden alle mouseclicks van de gebruiker gebufferd en na het berekenen alsnog verwerkt.

Even getest en het lijkt inderdaad het probleem te zijn. Je kan proberen om met een backgroundworker de waarde weg te schrijven, voorbeeldje:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    checkBox1.Enabled = false;
    this.Update();
    System.Diagnostics.Trace.WriteLine("Clicked checkbox");
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    System.Diagnostics.Trace.WriteLine("DoWork");
    System.Threading.Thread.Sleep(5000);
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    System.Diagnostics.Trace.WriteLine("BGW ready");
    checkBox1.Enabled = true;
}


Als je het zo oplost is volgens mij je probleem opgelost.

Hail to the king baby!


Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 12-09 16:17
Om dit probleem te begrijpen moet je snappen hoe windows werkt, bij een click wordt er een message gestuurd naar de applicatie, elke applicatie heeft een (single threaded) messageloop waarin die messages worden afgehandeld. Wat er in jou geval gebeurt is dat jouw eventhandler in de handler van die message in de messageloop wordt afgehandelt. Gedurende de update wordt dus de gehele messageloop gelocked totdat jouw eventhandler klaar is. Dit betekend dus dat tegen de tijd dat de volgende click gehandeld wordt je de checkbox alweer geenabled hebt. oplossing zou kunnen zijn om de update als het mogelijk is in een andere thread uit te voeren bijvoorbeeld met een backgroundworker.
Als dit niet mogelijk is(bijvoorbeeld als de update alleen in de UI thread uitgevoerd kan worden) zou je een timer kunnen inbouwen waardoor de checkbox er bijvoorbeeld een halve seconde lang na het uitvoeren van de update nog gedisabled blijft. In het event van de timer enable je hem dan vervolgens weer. (Het zal waarschijnlijk ook wel werken als je de timer op 1ms zet aangezien de meeste timer classes ook gewoon een message naar je applicatie sturen die vervolgens achterin de queue komt te staan waardoor deze pas na de clicks wordt afgehandelt.) De beste oplossing blijft natuurlijk om als het enigsinds mogelijk is om gewoon multithreaded te werken.

edit: ik moet wat vaker op F5 drukken

[ Voor 9% gewijzigd door jmzeeman op 26-02-2010 14:41 ]


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
@jmzeeman en urk_forever: dank voor die uitleg, hier kan ik echt mee verder :)

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Een simpele oplossing kan ook zijn om even Application.DoEvents() aan te roepen voor Enabled = True.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
pedorus schreef op vrijdag 26 februari 2010 @ 15:07:
Een simpele oplossing kan ook zijn om even Application.DoEvents() aan te roepen voor Enabled = True.
Maar dat zorgt er nog steeds voor dat je voor 5 seconden een non-responsive UI hebt. De oplossing van urk_forever is een stuk beter.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Woy schreef op vrijdag 26 februari 2010 @ 16:05:
[...]

Maar dat zorgt er nog steeds voor dat je voor 5 seconden een non-responsive UI hebt. De oplossing van urk_forever is een stuk beter.
Ik weet niet precies wat hier de situatie is, maar het lijkt erop dat je toch al met de UI-Thread van Excel zit, en dat Excel sowieso de UI-Thread gaat blokkeren tijdens de calculatie. Als je zomaar even de calculatie van Excel vanuit een andere Thread laat uitvoeren, dan zul je bugs krijgen omdat Excel hier niet op gebouwd is.

Maar in zijn algemeenheid ben ik normaal geen voorstander van DoEvents(), dus in die zin zijn we het eens. :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Ja ik heb ook gemerkt dat de calculatie in een andere thread uitvoeren niet de juiste oplossing is. Jammer eigelijk.

Application.DoEvents vind ik wel vies, maarja.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17:02
Woy schreef op vrijdag 26 februari 2010 @ 16:05:
Maar dat zorgt er nog steeds voor dat je voor 5 seconden een non-responsive UI hebt. De oplossing van urk_forever is een stuk beter.
Een popup die vermeld dat het ding bezig is is ook een optie, wat moet je met een responsive UI als je toch niets mag doen?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
farlane schreef op zaterdag 27 februari 2010 @ 00:17:
[...]


Een popup die vermeld dat het ding bezig is is ook een optie, wat moet je met een responsive UI als je toch niets mag doen?
Inderdaad, ik moet eens met hogeraf gaan bespreken hoe we het moeten doen.

Maar qua responsivness: er zijn 3 checkboxen.

Als je 1ntje aanklikt wordt er iets weggeschreven, klik je een andere aan wordt er iets ander weggeschreven.

Ik wil dus wel dat je de 2de nog kan aanklikken na de eerste. Dan wordt de data 2 maal gerefreshed (is de bedoeling). Dus de UI blocken is niet echt een goed idee.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
farlane schreef op zaterdag 27 februari 2010 @ 00:17:
[...]
Een popup die vermeld dat het ding bezig is is ook een optie, wat moet je met een responsive UI als je toch niets mag doen?
Een blocking UI thread zorgt er ook voor dat je Pop-UP niet geredrawed word. Het is niet erg dat je even moet wachten op een actie van de UI, maar het is wel belangrijk dat je de UI thread niet blokkeert. Nou weet ik niet precies hoe het met Excel zit, want als je de waarde in de UI thread moet updaten, en dat triggert meteen op dezelfde thread de herberekening, dan kan je er weinig aan veranderen.

Je moet altijd proberen te voorkomen dat je de UI thread voor langere tijd blokkeert, anders kan het voor de gebruiker lijken alsof de hele applicatie is vastgelopen. Een pop-up met een progress bar is natuurlijk wel een goede manier om je UI te blokkeren. Maar een responsive UI betekent niet perse dat je er ook wat in kunt doen.

[ Voor 3% gewijzigd door Woy op 27-02-2010 10:42 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

Topicstarter
Woy schreef op zaterdag 27 februari 2010 @ 10:41:
[...]

Een blocking UI thread zorgt er ook voor dat je Pop-UP niet geredrawed word. Het is niet erg dat je even moet wachten op een actie van de UI, maar het is wel belangrijk dat je de UI thread niet blokkeert. Nou weet ik niet precies hoe het met Excel zit, want als je de waarde in de UI thread moet updaten, en dat triggert meteen op dezelfde thread de herberekening, dan kan je er weinig aan veranderen.

Je moet altijd proberen te voorkomen dat je de UI thread voor langere tijd blokkeert, anders kan het voor de gebruiker lijken alsof de hele applicatie is vastgelopen. Een pop-up met een progress bar is natuurlijk wel een goede manier om je UI te blokkeren. Maar een responsive UI betekent niet perse dat je er ook wat in kunt doen.
Daar heb ik ook over nagedacht. Een te lange blokkeerende thread kan dat effect triggeren dat Windows zegt 'applicatie reageert niet'. En dat is ook niet de bedoeling.

Going for adventure, lots of sun and a convertible! | GMT-8

Pagina: 1