Domanda

Sto mostrando una schermata iniziale su un thread in background mentre il mio programma viene caricato.Una volta caricato, interrompo il thread poiché il suo unico scopo era mostrare un modulo splash in caricamento.

Il mio problema è che quando si interrompe un thread viene generato un file ThreadAbortException su cui l'utente può semplicemente fare clic su Continua.

Come posso affrontare questo problema?Stavo cercando di sopprimerlo in questo modo -->

            try
        {
            Program.splashThread.Abort();
        }
        catch(Exception ex)
        {

        }

ma ho la sensazione che mi farà sgridare qui e non funziona in alcun modo.

Grazie!

È stato utile?

Soluzione

Non è necessario per annullare il filo. Io incarno con il codice.

Nella forma schermata di avvio:

public void CloseSplash()
{
    Invoke((MethodInvoker)delegate
    {
        this.Close();
    });
}

Nel file Program.cs:

private static Splash _splash = null;
public static void CloseSplash()
{
    if (_splash!= null)
    {
        _splash.CloseSplash();
    }
}

Ora, quando il metodo Main inizia, mostrare il tonfo in un thread:

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
    _splash.ShowDialog();
}));

t.Start();

... e quando si vuole chiudere, basta chiuderlo:

Program.CloseSplash();

Quindi non c'è bisogno di preoccuparsi di abortire il filo; uscirà con grazia.

Altri suggerimenti

Si prega di fare riferimento al seguente link ottenuto facendo una ricerca su Google (primo risultato restituito):

http://msdn.microsoft.com/en-us/library /5b50fdsz.aspx

Prestare particolare attenzione a questa parte:

Quando questo metodo viene richiamato su un filo, il sistema getta un ThreadAbortException nel thread annullarla. ThreadAbortException è un'eccezione speciale che può essere catturato da codice dell'applicazione, ma viene ri-lanciata alla fine del blocco catch a meno che ResetAbort si chiama. ResetAbort Annulla la richiesta di interruzione, e impedisce il ThreadAbortException di terminare il filo. Non eseguiti blocchi finally vengono eseguite prima il filo viene interrotta.

Utilizzando Threadabort non è recommened. E 'il male. Perché non utilizzare un altro meccanismo come un (/ Manuale Auto) ResetEvent? Inizia il filo con la schermata iniziale, attendere l'evento. Se l'altro codice è fatto caricare roba, impostare l'evento en consentono la schermata iniziale per chiudere stesso modo normale (bello).

Alcuni punti.L'eccezione ThreadAbort È il motivo per cui il thread si interrompe.Non è un effetto collaterale della tua richiesta di interruzione.Quando si chiama abort su un thread, il runtime forza la propagazione di un'eccezione threadabort al thread.Questa eccezione può essere intercettata perché consente all'utente di eseguire alcune operazioni di pulizia prima che il thread venga interrotto.

L'eccezione viene quindi lanciata nuovamente automaticamente per garantire che il thread venga interrotto.Se l'eccezione venisse catturata e non venisse lanciata nuovamente, il thread non verrebbe mai interrotto.

Design davvero intelligente in realtà.

Quindi è davvero giusto cogliere questa eccezione.In effetti dovresti.Ma cogli solo quell’eccezione specifica e non l’eccezione generale.(come mostrato di seguito)

catch(ThreadAbortException ex)
{
   //This is an expected exception. The thread is being aborted
}

Cambia il tipo di eccezione per ThreadAbortException e aggiungere una chiamata a ResetAbort ()

    try
    {
        Program.splashThread.Abort();
    }
    catch(ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }

In generale, l'interruzione di discussioni è considerato molto cattiva pratica e può portare a tutti i tipi di difficile da rintracciare bug. Avete preso in considerazione per capire un modo per solo chiudere la finestra iniziale o utilizzare una sorta di polling per fermare il filo quando è stata impostata una bandiera?

Perché l'hai fatto? Basta impostare un flag che i sondaggi filo, poi alla fine quando il filo lo raccoglie lo chiuderanno in se.

Prova questo codice. Sta lavorando bene per me.

void splash()
{
    try {
        SplashScreen.SplashForm frm = new SplashScreen.SplashForm();
        frm.AppName = "HR";

        Application.Run(frm);
    }
    catch (ThreadAbortException ex)
    {
        Thread.ResetAbort();
    }
}

Ho usato la soluzione suggerita da Fredrik Mörk. E 'molto chiaro ed elegante. In caso contrario, ho trovato un problema se istanziamo il modulo di apertura prima di lanciare l'applicazione reale (application.run (mainform ...)):

solleva un invalidOprationException causata dalla forma-handle ancora non esiste nella chiamata-thread. Per creare il manico direttamente nel thread t (e saltare questa eccezione!) Provare a lanciare il modulo di apertura in questo modo:

Thread t = new Thread(new ThreadStart(delegate
{
    _splash = new Splash();
     Application.Run(_splash);
}));

t.Start();

e, se avete intenzione di chiamare il metodo closeSplash in più rami del programma, forzare il valore null dopo la prima chiamata:

    private static Splash _splash = null;
    public static void CloseSplash()
    {
        if (_splash!= null)
        {
            _splash.CloseSplash();
            _splash=null;
        }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top