private void HandleError(Exception ex)
        {
            lock (this)
            {
                // Per prima cosa occorre notificare l'utente che si è verificato un errore.
                // Poi decidiamo se siamo in condizione di recuperarlo.
                // In sostanza si possono verificare le seguenti eccezioni:
                // 1. User login exception: possiamo gestirla mostrando all'utente una schermata di login dopo aver inibito tutti i thread.
                // 2. Network Error: possiamo gestirla fermando tutti i thread e eseguendo controlli periodici con un bgworker che verifica la connetività di rete
                // 3. Eccezione non gestibile: qualcosa di molto brutto è accaduto e non sappiamo che farcene. Logghiamola su un logger e chiudiamo la baracca.

                Logger.LogError(ex);
                _mainWindow.NotifyError(ex.Message);
                if (ex is StartupException) {
                    var res = MessageBox.Show("La sincronizzazione iniziale non è andata a buon fine, errore: " + ex.InnerException.Message + ". Vuoi ritentare?", "Sincronizzazione fallita", MessageBoxButton.YesNo);
                    if (res == MessageBoxResult.Yes)
                        Startup();
                }
                else if (ex is UserLogoutException) {
                    var res = MessageBox.Show("Il logout non ha avuto successo, si vuole comunque procedere con l'eliminazione delle credenziali locali?","Logout remoto fallito", MessageBoxButton.YesNo);
                    if (res == MessageBoxResult.Yes)
                        UserCredentials.Reset();
                }
                else if (ex is NetworkException || ex is System.Net.Sockets.SocketException)
                {
                    // Se non è stata ancora presa alcuna decisione per questo genere di errore, eseguiamo la gestione
                    if (!_netErrorHandled)
                    {
                        _netErrorHandled = true;
                        ApplicationState.Instance.Pause();
                        _networkMonitor = new BackgroundWorker();
                        _networkMonitor.DoWork += (object sender, DoWorkEventArgs args) =>
                        {
                            UserCredentials cred = UserCredentials.Instance;
                            while (true)
                            {
                                try
                                {
                                    using (TcpClient c = new TcpClient())
                                    {
                                        c.Connect(cred.Host, cred.Port);
                                    }
                                    // Ok, finisce il worker
                                    break;
                                }
                                catch (Exception e)
                                {
                                    // Do nothing, la rete ancora giù
                                    continue; // Opzionale
                                }
                            }
                        };
                        _networkMonitor.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs args) =>
                        {
                            // A connessione ristabilita, riattiva tutti i thread
                            ApplicationState.Instance.Resume();
                            _netErrorHandled = false; // Richioso ma utile.
                        };
                        _networkMonitor.RunWorkerAsync();
                    }
                    //Altrimenti qualcuno sta già gestendo l'eccezione.
                }
                else if (ex is UserLoginException)
                {
                    ApplicationState.Instance.Pause();
                    LoginWindow lw = new LoginWindow();
                    bool? loginok = lw.ShowDialog();
                    if (loginok == null || loginok == false)
                    {
                        // Il login non è andato a buon fine
                        Shutdown(RETURN_VALUES.LOGIN_REFUSED);
                    }
                    else
                    {
                        // Il login è andato a buoin fine, facciamo ripartire tutto
                        ApplicationState.Instance.Resume();
                    }

                }
                else if (ex is FileInUseException)
                {
                    // In questo caso decido di ignorare l'errore che continuerà a presentarsi finchè l'utente
                    // modifica attivamente il file.
                }
                else
                {
                    Shutdown(RETURN_VALUES.GENERAL_ERROR);
                }
            }
        }
 public void RequireLogin()
 {
     Logger.LogInfo("Richiesto il login dell'utente.");
     LoginWindow _loginWindow = new LoginWindow();
     // Mostrare la UI di login
     _loginWindow.SetWaiting(false, "Si prega di eseguire il login");
     _loginWindow.ShowDialog();
     Startup();
 }