Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C# 2] programma werkt alleen in dev omgeving

Pagina: 1
Acties:

  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 16-09 20:30
Ik heb een programma in C# 2 gemaakt met verschillende threads, deze werkt prima onder Visual studio 2005. Echter als ik hem als stand alone run knalt hij in not responding nadat een thread is afgelopen. CPU gebruik blijft dan op nul staan.

De applicatie start een thread:
C#:
1
2
3
WatchThread = new Thread(new ThreadStart(threadFunctionWatcher));
WatchThread.Priority = ThreadPriority.AboveNormal;
WatchThread.Start();

Deze kijkt om de 5 seconden in een db of er nog een record gewijzigd is (in een tabel met 5 records, waar tijdstempels staan van de laatste update)

de thread:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void threadFunctionWatcher()
        {
                try
                {
                       //lalala zooi code....
                       Thread.Sleep(sleeptime);
                }

            }
            catch (ThreadAbortException) { }
            catch (Exception eExc)
            {
                Model.fireLogEvent(this, new LogNotificationEventArgs(eExc.Message, "DBWatcher:threadFunctionWatcher", 0, true));
            }
        }

Hij komt niet in de catch statement, deze geeft een melding op het scherm (als test).
Als ik de prioriteit anders instel verandert er niets

Als ik de thread niet start werkt de applicatie.
Applicatie loopt (volgens mij) tot de sleep, dan is de cpu belasting 0 en dan hangt ie.

Wat kan er aan de hand zijn?

EDIT: sleep is het niet, als ik deze uitschakel loopt hij ook vast

EDIT2:
huidige thread hoogste prio gegeven werkte ook niet. Het lijkt erop dat de hoofdthread niet meer mee doet ofzo. Of moet ik iets van DoEvents(); gaan aanroepen oid?

[ Voor 12% gewijzigd door elgringo op 01-08-2007 15:36 ]

if broken it is, fix it you should


  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Debug de method die je op een andere thread uitvoert eens.
Ben je zeker dat er geen exceptie gegooid wordt binnen die functie ?
Ga je ergens je UI gaan updaten vanuit die thread ?

https://fgheysels.github.io/


  • Not Pingu
  • Registratie: November 2001
  • Laatst online: 20-11 21:40

Not Pingu

Dumbass ex machina

Heb je misschien noodzakelijke bestanden in je debug directory staan die niet in je release directory staan?

Certified smart block developer op de agile darkchain stack. PM voor info.


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 30-11 19:45

TeeDee

CQB 241

Staat er in je threadFunctionWatcher (in de zooi code) misschien wat DataAccess rommel? Zo ja, weet je zeker dat je App.config goed ingesteld is? Test <> Productie Database?

Heart..pumps blood.Has nothing to do with emotion! Bored


  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Eigenljik heeft dit topic op dit moment geen enkele zin; het enige wat we nu kunnen doen is gissen en raden.
Dus, ik denk dat we best ff wachten tot wanneer de TS z'n zooi gedebugged heeft, en met wat meer gerichte informatie kan afkomen (of misschien heeft hij dan z'n probleem wel zelf kunnen oplossen)

https://fgheysels.github.io/


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 16-09 20:30
whoami schreef op woensdag 01 augustus 2007 @ 16:50:
Debug de method die je op een andere thread uitvoert eens.
Ben je zeker dat er geen exceptie gegooid wordt binnen die functie ?
Ga je ergens je UI gaan updaten vanuit die thread ?
Hoe kan je dan aangeven dat je op een andere thread wil debuggen. (ik gebruik nu de VS2005 debug knop ;) )
Functie gooit geen exceptie. Zit een handler in die het laat zien. (Messagebox)
UI wordt niet direct geupdate. En wordt een datatabel aangepast een event afgevuurd en de handler update de datatable in de ui. De handler:

C#:
1
2
3
4
5
6
7
8
9
10
void Model_TablesUpdated(string tablename)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Model.TablesUpdatedEvent(Model_TablesUpdated), new object[] { tablename });

                return;
            }
            // hier worden de tables gereset
}


Nog ff ter aanvulling:
Het is niet het programma wat vast loopt. Aan de events worden n iet meer afgeven, vanwege de threads. De applicatie doett zijn werk wel (zie ik aande output). Dan zal DoEvents() de oplossing moeten geven, maar dat helaas niet zo te zijn (of niet hoe ik hem gebruik (en dat is in elke thread voor de sleep))

Ik mis dus geen bestanden of een database oid.

EDIT:
Bij het updaten van de UI gaat het mis. De datatable wordt aangepast en moet getoond worden, dat gaat in die handler (die hierboven staat) met de code:
C#:
1
bsArtikel.ResetBindings(true);


Deze is gemaakt alsvolgt:
C#:
1
2
3
bsArtikel = new BindingSource();
                bsArtikel.DataSource = Model.ArtikelTable;
                dataGridViewArtikel.DataSource = bsArtikel;

En Model.ArtikelTable is een statische datatable die gevuld wordt door een thread (wordt eerst gelockt). Dat gaat zo: (deze methode wordt in de thread aangeroepen)

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void updateArtikelTables()
        {
            try
            {
                lock (Model.ArtikelTable)
                {
                    Model.ArtikelTable.Clear();
                    _DataAdapterArtikel.Fill(Model.ArtikelTable);
                    Model.fireTableEvent(Model.ArtikelTable.TableName);
                }
            }
            catch (Exception eExc)
            {
                Model.fireLogEvent(this, new LogNotificationEventArgs(eExc.Message, "DBWatcher:updateArtikelTables", 0, false));
            }
        }


EDIT 2:

Ik de 2de thread heb ik nu de sleep staan. Als ik deze weghaal en Application.DoEvents() er neer zet werkt het. Als ik deze icm de sleep er neer zet niet. MAW het lijkt erop dat tijdens de sleep geen events gehandled worden. Kan dit kloppen?
Als ik overigens de datatable in de thread niet vul (en dus het event) niet afgevuurd wordt, blijft hij wel werken. Of is de manier van dataoverdracht niet geheel threadsafe?

De Een oplossing heb ik ook gevonden: Als de datagridview die gevuld wordt niet zichtbaar is en hij wordt dan gevuld is het geen probleem. Het aanpassen van de data terwijl hij zichtbaar is, is het probleem.

[ Voor 61% gewijzigd door elgringo op 02-08-2007 09:02 ]

if broken it is, fix it you should


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Ik snap nog niet helemaal hoe je applicatie nu in elkaar zit.
Je hebt een applicatie die een window toont waarvan de gegevens elke X tijd bijgewerkt moeten worden?

Als dat zo is kun je dan niet beter een Timer gebruiken ipv zelf een thread te bouwen.

Wanneer je toch voor de thread aanpak wil gaan kun je het volgende proberen:
Code voor de thread
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ThreadClass {
    public void Run() {
        try {
            while(true) {
                // Doe moeilijke en langdurige dingen
                Thread.Sleep(sleepTimeout);
            }
        } catch(ThreadAbortException) {
            // Dit wil je wel afvangen :P
        } catch(Exception ex) {
            // Doe hier ook iets mee
        }
    }
}

Code voor het main window
C#:
1
2
3
4
5
6
7
8
9
10
public class Program {
    public static void Main(string[] args) {
        // Start je form etc

        // Start de thread
        ThreadClass tc = new ThreadClass();
        Thread t = new Thread(new ThreadStart(tc.Run));
        t.Run();
    }
}


De while-loop in de ThreadClass is om er voor te zorgen dat de thread blijft lopen en niet na 1x stopt.

@Jouw laatste edit:
Wordt de data niet goed ververst dan? Misschien moet je nog even BindingSource.ResetBindings() aanroepen.

[ Voor 9% gewijzigd door MTWZZ op 02-08-2007 09:05 ]

Nu met Land Rover Series 3 en Defender 90


  • MrSleeves
  • Registratie: Februari 2004
  • Laatst online: 13-10 22:03

MrSleeves

You'll thank me later.

elgringo schreef op donderdag 02 augustus 2007 @ 07:49:
[...]

Ik de 2de thread heb ik nu de sleep staan. Als ik deze weghaal en Application.DoEvents() er neer zet werkt het. Als ik deze icm de sleep er neer zet niet. MAW het lijkt erop dat tijdens de sleep geen events gehandled worden. Kan dit kloppen?
Die thread doet dan niks en wacht tot de ingestelde tijd voorbij is.
Als ik overigens de datatable in de thread niet vul (en dus het event) niet afgevuurd wordt, blijft hij wel werken. Of is de manier van dataoverdracht niet geheel threadsafe?

De Een oplossing heb ik ook gevonden: Als de datagridview die gevuld wordt niet zichtbaar is en hij wordt dan gevuld is het geen probleem. Het aanpassen van de data terwijl hij zichtbaar is, is het probleem.
Weet je zeker dat er in die thread geen UI-functies worden aangeroepen?
Je kan zoiets ondervangen met InvokeRequired.

30Drie Web Design & IT Consultancy | Raven Consultancy Services


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 16-09 20:30
MTWZZ schreef op donderdag 02 augustus 2007 @ 09:03:
Ik snap nog niet helemaal hoe je applicatie nu in elkaar zit.
Je hebt een applicatie die een window toont waarvan de gegevens elke X tijd bijgewerkt moeten worden?

Als dat zo is kun je dan niet beter een Timer gebruiken ipv zelf een thread te bouwen.

Wanneer je toch voor de thread aanpak wil gaan kun je het volgende proberen:
Code voor de thread
...
Code voor het main window
...

De while-loop in de ThreadClass is om er voor te zorgen dat de thread blijft lopen en niet na 1x stopt.

@Jouw laatste edit:
Wordt de data niet goed ververst dan? Misschien moet je nog even BindingSource.ResetBindings() aanroepen.
Ik heb een database met een aantal grote tabellen die getoond moeten worden aan de gebruiker. Maar pas als de db verandert is (dit wordt uit een table gehaald waar een tijd staat wanneer de laatste aanpassing was). Ik heb anders geprobeerd maar dit werkt in principe goed.

De thread heeft idd een while(true) en slaapt telkens 5 seconde en kijk dan of de tijd is aangepast en past dan evt de data aan.

Thread wordt ook aangemaakt zoals jij beschrijft.

De data wordt te goed ververst. Als ik geen event vuur dat de datatable aangepast is (en dus resetbindings niet uitgevuurd wordt) worden de wijziging toch getoond. Dit is in de debug omgeving NIET het geval en werkt het alleen als resetbindings wel wordt aangeroepen.

De datatable wordt zo gevuld:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try
            {
                lock (Model.ProductenTable)
                {
                   // Model.ProductenTable.BeginLoadData();
                   
                    Model.fireTableBlockEvent(Model.ProductenTable.TableName);
                    Model.ProductenTable.Clear();
                    _DataAdapterProducten.Fill(Model.ProductenTable); 
                  //  Model.ProductenTable.EndLoadData();
                    Model.fireTableEvent(Model.ProductenTable.TableName);
                }
            }
            catch (Exception eExc)
            {
                Model.fireLogEvent(this, new LogNotificationEventArgs(eExc.Message, "DBWatcher:updateProductenTables", 0, true));
            }

De fireTableBlockEvent is ff een test die de bindingsource stilzet:
C#:
1
bs.SuspendBinding();

en na de update wordt hij met resume weer 'aangezet'.

BeginLoadData en EndLoadData heb ik getest zodat data niet ververst wordt in de guis. Maar als ik dit doe (en EndLoadData NIET aanroept wordt hij alsnog getoond.

Verder heb ik bij de bindingsource in begin supendbinding aangeroepen, alles aangepast en resumebinding. Ook dit werkt niet en de data werd ververst.

@MrSleeves:
De eventhandler na de datatable update zit een invoke in. Echter, zoals ik hierbonven vertel, is deze methode niet nodig om de data aan te passen en gaat het vanzelf. het vreemde is dat in de VS2005 omgeving niet is en dat ik geforceerd (met bindingsource.resetbindings) de data moet laten tonen.

Ik denk nu dat het probleem is dat de data vanuit een andere thread geupdate wordt en dat ik daardoor deze situatie krijg. Ik ikan echter niet zorgen dat hij vanuit de goeie thread gebeurd om het vanzelf gaat....

[ Voor 11% gewijzigd door elgringo op 02-08-2007 09:32 ]

if broken it is, fix it you should


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 16-09 20:30
Nog ff kort samengevat: De data updaten werkt prima, maar als de datagridview die geupdate wordt zichtbaar is reageert deze datagridview erg traag op events (scrollen bijv). Als hij geupdate wordt en hij is niet getoond (ander tabblad is zichtbaar) is er geen probleem en worden de events (het scrollen) wel snel afgehandeld.

En in VS2005 omgeving heb ik hier totaal geen last van.

Ik heb inmiddels ook wat geprobeerd:
De data in de datagridview is via een bindingsource aan een datatable gekoppeld die door de thread gevuld wordt.
- Zonder bindingsource hetzelfde probleem
- Datatable blokkeren en vrijgeven heeft geen zin, het probleem doet zich voor als hij vrijgegven wordt
- met of zonder Lock tijdens vullen van datatable

Ik moet zeggen dat het ebst frusterend is, als hij wel in VS2005 werkt en niet stand-alone (mss moet is vs2005 maar erbij leveren ;) )

Of is het misschien iets met de binding van de datasource aan de datagridview? Aangezien het probleem zich pas voordoet als de data verandert. Een oplossing wat wel geen sleep in de thread en constant DoEvents aanroepen. Hebben die dan wat met elkaar te maken?

EDIT:
Het probleem is dat de events niet meer afgehandeld worden. Zodra de thread gaat slapen doet hij niets meer. Pas als hij wat gaat doen worden de events afgehandeld. Dan blijft de volgende vraag (en dit is hem...) over: Waarom worden de events niet afgehandeld als de thread aan het slapen is en de data gevuld is. (als de data niet gevuld wordt en de thread wel loopt heeft ie dit probleem niet). Oftewel, zorgt die datatable ervoor dat mijn events niet meer afgehandeld worden? En die events, die niet afgehandeld worden, zijn alleen van de datagridview die aan die datatable gekoppeld is

[ Voor 77% gewijzigd door elgringo op 02-08-2007 11:37 ]

if broken it is, fix it you should


  • elgringo
  • Registratie: Januari 2001
  • Laatst online: 16-09 20:30
Ik heb de oplossing gevonden, en waarschijnlijk ook het probleem.

Het probleem is dat de datatable door een andere thread dan de gui gevuld wordt deze wordt aan de datagridview gekoppeld en het lijkt dat dan de messagequeue, voor de events, ook naar die thread mee verhuist, waardoor hij niet meer werkt.

De oplossing. Zodra de data verandert is een event geven en gui thread laten vullen. Nadeel hiervan is dat deze ff stilligt (max 8 seconde met 15000 records). Maar das te overzien.

if broken it is, fix it you should

Pagina: 1