Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2005
    Messaggi
    75

    [C#] programma si blocca su doEvents

    ciao a tutti sto scrivendo un programma che deve leggere dei dati su una porta e il programma sostanzialmente funziona xkè tramite il metodo Print di System.diagnostic.debug ho constatato che i dati li riceve correttamente. Il mio problema è che questo codice è inserito in un timer che viene eseguito ogni 10 millisecondi e al suo interno c'è l'istruzione application.DoEvents() per non fare bloccare l'applicazione, ma dopo un pò che il programma è in esecuzione e funziona correttamente mi esce il segunte errore :" Eccezione non gestita di tipo 'System.StackOverflowException' in System.Windows.Forms.dll" e l'esecuzione mi si blocca per l'appunto sull'istruzione application.doEvents().

    vi posto il codice
    codice:
    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                Application.DoEvents();  <== l'errore è qui
    
                string command = leggiFlusso.ReadLine();
    
                if (command.Equals("WALK"))
                {
                    foreach (tassello tas in snake)
                        tas.Location = tas.newPoint;
                }
                else
                {
                    System.Diagnostics.Debug.Print(command);
                    switch (cont)
                    {
                        case 0:
                            p = new Point();
                            p.X = int.Parse(command);
                            cont++;
                            break;
    
                        case 1:
                            p.Y = int.Parse(command);
                            cont++;
                            break;
    
                        case 2:
                            if (int.Parse(command) <= snake.Count - 1)
                            {
                                snake[int.Parse(command)].newPoint = p;
                                //System.Diagnostics.Debug.Print("creo il tassello");
                                //System.Diagnostics.Debug.Print(command);
                            }
                            else
                            {
                                if (snake.Count <= 2)
                                    this.creaTassello(p, snake.Count);
                                else
                                {
                                    this.creaTassello(p, 2);
                                    snake[snake.Count - 2].Image = img[1];
                                }
                            }
    
                            cont = 0;
                            break;
                    }
                }
            }
    ma perchè mi da questo errore ?

    grazie ciao luca

  2. #2
    Prova a mettere all'inizio
    codice:
    timer.Enabled = false;
    e alla fine
    codice:
    timer.Enabled = true;
    .
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2005
    Messaggi
    75
    grazie MItaly ho provato e il tuo metodo funziona. ... anche se non ho ben capito perchè ...

    comunque io quel codice l'ho messo solo provissoriamente in un timer, in quanto volevo includerlo in un ciclo while solo che, nel timer posso fare con il metodo che tu mi hai descritto, ma in un ciclo while come faccio?

    Ti posto il nuovo codice:
    codice:
    private void riceviDati()
            {
                while (true)
                {
                   Application.DoEvents();    <== l'errore è sempre qui  
    
                    int num = 0;
                    string command = leggiFlusso.ReadLine();
    
                    if (command.Equals("WALK"))
                    {
                        foreach (tassello tas in snake)
                            tas.Location = tas.newPoint;
                    }
                    else
                    {
    
                        num = int.Parse(command);
    
                        switch (cont)
                        {
                            case 0:
                                p = new Point();
                                p.X = num;
                                cont++;
                                break;
    
                            case 1:
                                p.Y = num;
                                cont++;
                                break;
    
                            case 2:
                                this.pos = num;
                                cont++;
                                break;
    
                            case 3:
                                if (num <= snake.Count - 1)
                                {
                                    if (snake[num].pos != this.pos)
                                    {
                                        Bitmap newImg = new Bitmap(img[snake[num].tipo]);
                                        newImg.RotateFlip((RotateFlipType)this.pos);
                                        snake[num].Image = newImg;
                                        snake[num].pos = this.pos;
                                    }
    
                                    snake[num].newPoint = p;
    
                                }
                                else
                                {
                                    if (snake.Count <= 2)
                                        this.creaTassello(p, snake.Count);
                                    else
                                    {
                                        this.creaTassello(p, 2);
                                        snake[snake.Count - 2].Image = img[1];
                                    }
                                }
    
                                cont = 0;
                                break;
                        }
                    }
                }
            }
    grazie per l'aiuto

    luca

  4. #4
    Originariamente inviato da snake88m
    grazie MItaly ho provato e il tuo metodo funziona. ... anche se non ho ben capito perchè ...
    Quando tu chiami DoEvents crei un nuovo message loop che recapita tutti i messaggi delle finestre del thread corrente alle appropriate window procedure; tuttavia tra questi messaggi potrebbe esserci anche il WM_TIMER (quello che il .NET Framework traduce in un evento Timer.Elapsed), dal momento che hai impostato un intervallo di tempo piuttosto piccolo, per cui la DoEvents richiamerà timer_Elapsed, il quale a sua volta richiamerà la DoEvents, che probabilmente richiamerà timer_Elapsed e così via fino a quando lo stack non si esaurisce (guardando lo stack trace al momento dell'errore potrai avere conferma della mia spiegazione).
    codice:
    private void riceviDati()
            ...
    Per caso anche riceviDati viene richiamato da un evento del form?
    Non ti conviene eseguire la ricezione dei dati in un thread separato lasciando stare la DoEvents?
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Dec 2005
    Messaggi
    75
    ciao ho provato a fare come dici te, e cioè a usare i thread (non sapevo che si potesse fare una cosa del genere). Alla fine ho fatto così: ho creato un thread con il compito di ascoltare i dati provenienti da una porta e man mano che riceve i dati, a seconda dei valori che riceve deve muovere delle picturebox sulla form. Solo che mi restituisce il seguente errore: "Operazione cross-thread non valida: è stato eseguito l'accesso al controllo 'frmGame' da un thread diverso da quello da cui è stata eseguita la creazione."
    Da quello che ho capito la modifica degli oggetti grafici (Control) di una form può essere eseguita solo dal thread principale e per ovviare a ciò ho provato a usare dei delegati. Solo che il problema rimane e continua a darmi lo stesso identico errore.

    posto il codice:

    codice:
    delegate void delegaCreaTassello(Point p, int tipo);
    delegate void delegaMuovi();
    
     private void creaTassello(Point p, int tipo)  <== metodo richiamato tramite delegato
            {
                tassello tas = new tassello(p, tipo, 0);
                tas.Image = img[tipo];
                tas.Size = new Size(30, 30);
                tas.Location = p;
                snake.Add(tas);
                this.Controls.Add(tas); <== qui restituisce l'errore (se commento questa riga l'errore viene restituito nel metodo sottostante
                System.Diagnostics.Debug.Print("pic aggiunta");
            }
    
    
            private void muovi() <== metodo richiamato tramite delegato
            {
                foreach (tassello tas in snake)
                    tas.Location = tas.newPoint; <== errore
            }
    
    
            private void riceviDati()
            {
                while (true)
                {
                    int num = 0;
                    string command = leggiFlusso.ReadLine();
    
                    if (command.Equals("WALK"))
                    {
                        delegaMuovi muoviTas = new delegaMuovi(this.muovi); <== nuova istanza
                        muoviTas(); <== richiamo il metodo muovi(più sopra) tramite delegato
                    }
                    else
                    {
    
                        num = int.Parse(command);
    
                        switch (cont)
                        {
                            case 0:
                                p = new Point();
                                p.X = num;
                                cont++;
                                break;
    
                            case 1:
                                p.Y = num;
                                cont++;
                                break;
    
                            case 2:
                                this.pos = num;
                                cont++;
                                break;
    
                            case 3:
                                if (num <= snake.Count - 1)
                                {
                                    if (snake[num].pos != this.pos)
                                    {
                                        Bitmap newImg = new Bitmap(img[snake[num].tipo]);
                                        newImg.RotateFlip((RotateFlipType)this.pos);
                                        snake[num].Image = newImg;
                                        snake[num].pos = this.pos;
                                    }
    
                                    snake[num].newPoint = p;
    
                                }
                                else
                                {
                                    delegaCreaTassello newTassello = new delegaCreaTassello (this.creaTassello);
    
                                    if (snake.Count <= 2)
                                        newTassello(p, snake.Count); <== richiamo il metodo creaTassello (più sopra)
                                    else
                                    {
                                        newTassello(p, 2);
                                        snake[snake.Count - 2].Image = img[1];
                                    }
                                }
    
                                cont = 0;
                                break;
                        }
                    }
                }
            }
    help please

    ciao e grazie
    luca

  6. #6
    Non avevo visto che ci sono operazioni su controlli Windows Forms... be', in questo caso sarebbe un po' un casino usare le soluzioni che si usano normalmente in queste situazioni, meglio riportare tutto a com'era prima
    Ti chiedo di nuovo (riferendomi al codice di prima):
    Per caso anche riceviDati viene richiamato da un evento del form?
    .
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2005
    Messaggi
    75
    si il metodo riceviDati viene richiamato da un evento del form. In questo caso il Form_Load.
    Aggiungo anche che il suddetto metodo (riceviDati) lo eseguo in un altro thread

    codice:
                Thread thrDati = new Thread(new ThreadStart(this.riceviDati));
                thrDati.Start();

  8. #8
    Forse è meglio se zippi tutto il progetto e mi ci fai dare un'occhiata direttamente...
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.