Risoluzione dei problemi relativi alle eccezioni: System.InvalidOperationException
Un'eccezione InvalidOperationException viene generata quando viene chiamato un metodo di un oggetto, se lo stato dell'oggetto non può supportare la chiamata al metodo. L'eccezione viene generata anche quando un metodo tenta di modificare l'interfaccia utente da un thread che non è il thread principale o il thread dell'interfaccia utente.
Importante
Poiché le eccezioni InvalidOperationException possono essere generate in una serie infinita di circostanze, è importante leggere e comprendere il messaggio Message visualizzato nelle Informazioni sulle eccezioni.
In questo articolo
Un metodo in esecuzione su un thread non dell'interfaccia utente aggiorna l'interfaccia utente
Un'istruzione in un blocco foreach (For Each in Visual Basic) modifica la raccolta durante lo scorrimento
Viene eseguito il cast a T di un oggetto Nullable<T> null
Un metodo System.Linq.Enumerable viene chiamato su una raccolta vuota
Articoli correlati
Gli esempi di codice in questo articolo illustrano come alcune eccezioni InvalidOperationException comuni possono verificarsi nell'app. Il modo in cui vengono gestiti i problemi dipende dalla situazione specifica. Se l'eccezione è irreversibile per la funzionalità dell'app, è possibile usare un costrutto try … catch (Try .. Catch in Visual Basic) per acquisire l'eccezione e pulire lo stato dell'app prima di uscire. Altre eccezioni InvalidOperationException possono però essere previste ed evitate. Gli esempi dei metodi rivisti illustrano alcune di queste tecniche.
Un metodo in esecuzione su un thread non dell'interfaccia utente aggiorna l'interfaccia utente
Generazione di un'eccezione InvalidOperationException con un aggiornamento dell'interfaccia utente da un thread non dell'interfaccia utente | Evitare le eccezioni InvalidOperationException su thread non dell'interfaccia utente
La maggior parte dei framework delle app per la GUI (interfaccia grafica utente) .NET, ad esempio Windows Form e Windows Presentation Foundation (WPF), consente di accedere agli oggetti della GUI solo dal thread che crea e gestisce l'interfaccia utente, ovvero dal thread principale o dell'interfaccia utente. Un'eccezione InvalidOperationException viene generata quando si tenta di accedere a un elemento dell'interfaccia utente da un thread non dell'interfaccia utente.
Generazione di un'eccezione InvalidOperationException con un aggiornamento dell'interfaccia utente da un thread non dell'interfaccia utente
Nota
Gli esempi seguenti usano Modello asincrono basato su attività (TAP) per creare thread non dell'interfaccia utente.Tuttavia, gli esempi riguardano anche tutti i Modelli di programmazione asincrona .NET.
In questi esempi, il gestore eventi ThreadsExampleBtn_Click chiama il metodo DoSomeWork due volte. La prima chiamata al metodo (DoSomeWork(20);) viene eseguita in modo sincrono e completata con esito positivo. La seconda chiamata (Task.Run( () => { DoSomeWork(1000);});) viene eseguita invece su un thread nel pool di thread dell'app. Poiché questa chiamata tenta di aggiornare l'interfaccia utente da un thread non dell'interfaccia utente, l'istruzione genera un'eccezione InvalidOperationException.
App Store e WPF
Nota
Nelle app di Store Phone, viene generata un'eccezione Exception anziché l'eccezione InvalidOperationException più specifica.
Messaggi di eccezione:
App WPF |
Altre informazioni: Impossibile accedere all'oggetto dal thread chiamante perché tale oggetto è di proprietà di un altro thread. |
Applicazioni Windows Store |
Altre informazioni: L'applicazione ha chiamato un'interfaccia su cui era stato eseguito il marshalling per un thread differente. (Eccezione da HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)) |
private async void ThreadsExampleBtn_Click(object sender, RoutedEventArgs e)
{
TextBox1.Text = String.Empty;
TextBox1.Text = "Simulating work on UI thread.\n";
DoSomeWork(20);
TextBox1.Text += "Simulating work on non-UI thread.\n";
await Task.Run(() => DoSomeWork(1000));
TextBox1.Text += "ThreadsExampleBtn_Click completes. ";
}
private void DoSomeWork(int msOfWork)
{
// simulate work
var endTime = DateTime.Now.AddMilliseconds(msOfWork);
while (DateTime.Now < endTime)
{
// spin
};
// report completion
var msg = String.Format("Some work completed in {0} ms on UI thread. \n", msOfWork);
TextBox1.Text += msg;
}
App di Windows Form
Messaggio di eccezione:
- Altre informazioni: Operazione cross-thread non valida: è stato eseguito l'accesso al controllo 'TextBox1' da un thread diverso da quello da cui è stata eseguita la creazione.
private async void ThreadsExampleBtn_Click(object sender, EventArgs e)
{
TextBox1.Text = String.Empty;
var tbLinesList = new List<string>() {"Simulating work on UI thread."};
TextBox1.Lines = tbLinesList.ToArray();
DoSomeWork(20, tbLinesList);
tbLinesList.Add("Simulating work on non-UI thread.");
TextBox1.Lines = tbLinesList.ToArray();
await Task.Run(() => DoSomeWork(1000, tbLinesList));
tbLinesList.Add("ThreadsExampleBtn_Click completes.");
TextBox1.Lines = tbLinesList.ToArray();
}
private void DoSomeWork(int msOfWork, List<string> tbLinesList)
{
// simulate work
var endTime = DateTime.Now.AddMilliseconds(msOfWork);
while (DateTime.Now < endTime) { };
{
// spin
};
// report completion
var msg = String.Format("Some work completed in {0} ms on UI thread. \n", msOfWork);
tbLinesList.Add(msg);
TextBox1.Lines = tbLinesList.ToArray();
}
Contenuto dell'articolo
Contenuto della sezione
Evitare le eccezioni InvalidOperationException su thread non dell'interfaccia utente
I framework dell'interfaccia utente di Windows implementano un modello dispatcher che include un metodo per verificare se una chiamata a un membro di un elemento dell'interfaccia utente viene eseguita sul thread dell'interfaccia utente e altri metodi per pianificare la chiamata sul thread dell'interfaccia utente.
App WPF
Nelle app WPF usare uno dei metodi Dispatcher.Invoke per eseguire un delegato sul thread dell'interfaccia utente. Se necessario, usare il metodo Dispatcher.CheckAccess per determinare se un metodo è in esecuzione su un thread non dell'interfaccia utente.
private void DoSomeWork(int msOfWork)
{
var endTime = DateTime.Now.AddMilliseconds(msOfWork);
while (DateTime.Now < endTime)
{
// spin
};
// report completion
var msgFormat = "Some work completed in {0} ms on {1}UI thread.\n";
var msg = String.Empty;
if (TextBox1.Dispatcher.CheckAccess())
{
msg = String.Format(msgFormat, msOfWork, String.Empty);
TextBox1.Text += msg;
}
else
{
msg = String.Format(msgFormat, msOfWork, "non-");
Action act = ()=> {TextBox1.Text += msg;};
TextBox1.Dispatcher.Invoke(act);
}
}
App di Windows Form
Nelle app di Windows Form usare il metodo Control.Invoke per eseguire un delegato che aggiorna il thread dell'interfaccia utente. Se necessario, usare la proprietà Control.InvokeRequired per determinare se un metodo è in esecuzione su un thread non dell'interfaccia utente.
private void DoSomeWork(int msOfWork, List<string> tbLinesList)
{
// simulate work
var endTime = DateTime.Now.AddMilliseconds(msOfWork);
while (DateTime.Now < endTime)
{
// spin
};
// report completion
var msgFormat = "Some work completed in {0} ms on {1}UI thread.\n";
var msg = String.Empty;
if (TextBox1.InvokeRequired)
{
msg = String.Format(msgFormat, msOfWork, "non-");
tbLinesList.Add(msg);
Action act = () => TextBox1.Lines = tbLinesList.ToArray();
TextBox1.Invoke( act );
}
else
{
msg = String.Format(msgFormat, msOfWork, String.Empty);
tbLinesList.Add(msg);
TextBox1.Lines = tbLinesList.ToArray();
}
}
Applicazioni Windows Store
Nelle app dello Store usare il metodo CoreDispatcher.RunAsync per eseguire un delegato che aggiorna il thread dell'interfaccia utente. Se necessario, usare la proprietà HasThreadAccess per determinare se un metodo è in esecuzione su un thread non dell'interfaccia utente.
private void DoSomeWork(int msOfWork)
{
// simulate work
var endTime = DateTime.Now.AddMilliseconds(msOfWork);
while (DateTime.Now < endTime)
{
// spin
};
// report completion
var msgFormat = "Some work completed in {0} ms on {1}UI thread.\n";
var msg = String.Empty;
if (TextBox1.Dispatcher.HasThreadAccess)
{
msg = String.Format(msgFormat, msOfWork, String.Empty);
TextBox1.Text += msg;
}
else
{
msg = String.Format(msgFormat, msOfWork, "non-");
TextBox1.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
()=> {TextBox1.Text += msg;});
}
}
Contenuto dell'articolo
Contenuto della sezione
Un'istruzione in un blocco foreach (For Each in Visual Basic) modifica la raccolta durante lo scorrimento
Generazione di un'eccezione InvalidOperationException con foreach | Evitare le eccezioni InvalidOperationException nei cicli
Un'istruzione foreach (For Each in Visual Basic) ripete un gruppo di istruzioni incorporate per ogni elemento in una matrice o una raccolta che implementa l'interfaccia IEnumerable o IEnumerable. L'istruzione foreach viene usata per scorrere la raccolta per leggere e modificare gli elementi, ma non può essere usata per aggiungere o rimuovere elementi dalla raccolta. Un'eccezione InvalidOperationException viene generata se si aggiungono o rimuovono elementi dalla raccolta di origine in un'istruzione foreach.
Generazione di un'eccezione InvalidOperationException con foreach
In questo esempio, un'eccezione InvalidOperationException viene generata quando l'istruzione numList.Add(5); tenta di modificare l'elenco nel blocco foreach.
Messaggio di eccezione:
- Altre informazioni: Raccolta modificata. Impossibile eseguire l'operazione di enumerazione.
private void AddElementsToAList()
{
var numList = new List<int>() { 1, 2, 3, 4 };
foreach (var num in numList)
{
if (num == 2)
{
numList.Add(5);
}
}
// Display list elements
foreach (var num in numList)
{
Console.Write("{0} ", num);
}
}
Contenuto dell'articolo
Contenuto della sezione
Evitare le eccezioni InvalidOperationException nei cicli
Importante
L'aggiunta o la rimozione di elementi in un elenco durante lo scorrimento della raccolta può avere effetti collaterali imprevisti e difficili da prevedere.Se possibile, è consigliabile spostare l'operazione al di fuori dello scorrimento.
private void AddElementsToAList ()
{
var numList = new List<int>() { 1, 2, 3, 4 };
var numberOf2s = 0;
foreach (var num in numList)
{
if (num == 2)
{
numberOf2s++;
}
}
for (var i = 0; i < numberOf2s; i++ )
{
numList.Add(5);
}
// Display list elements
foreach (var num in numList)
{
Console.Write("{0} ", num);
}
}
Se è necessario aggiungere o rimuovere elementi in un elenco durante lo scorrimento di una raccolta, usare un ciclo for (For in Visual Basic):
private void AddElementsToAList ()
{
var numList = new List<int>() { 1, 2, 3, 4 };
for (var i = 0; i < numList.Count; i++)
{
if (numList[i] == 2)
{
numList.Add(5);
}
}
// Display list elements
foreach (var num in numList)
{
Console.Write("{0} ", num);
}
}
Contenuto dell'articolo
Contenuto della sezione
Viene eseguito il cast a T di un oggetto Nullable<T> null
Generazione di un'eccezione InvalidOperationException con un cast non valido | Evitare l'eccezione InvalidOperationException da un cast non valido
Se si esegue il cast di una struttura Nullable null (Nothing in Visual Basic) al relativo tipo sottostante, viene generata un'eccezione InvalidOperationException.
Generazione di un'eccezione InvalidOperationException con un cast non valido
In questo metodo, un'eccezione InvalidOperationException viene generata quando il metodo Select esegue il cast di un elemento null di dbQueryResults a un int.
Messaggio di eccezione:
- Altre informazioni: L'oggetto nullable deve avere un valore.
private void MapQueryResults()
{
var dbQueryResults = new int?[] { 1, 2, null, 4 };
var ormMap = dbQueryResults.Select(nullableInt => (int)nullableInt);
//display map list
foreach (var num in ormMap)
{
Console.Write("{0} ", num);
}
Console.WriteLine();
}
Contenuto dell'articolo
Contenuto della sezione
Evitare l'eccezione InvalidOperationException da un cast non valido
Per evitare InvalidOperationException:
Usare la proprietà Nullable.HasValue per selezionare solo gli elementi che non sono null.
Usare uno dei metodi Nullable.GetValueOrDefault di overload per fornire un valore predefinito per un elemento null.
Esempio Nullable<T>.HasValue
private void MapQueryResults()
{
var dbQueryResults = new int?[] { 1, 2, null, 4 };
var ormMap = dbQueryResults
.Where(nulllableInt => nulllableInt.HasValue)
.Select(num => (int)num);
//display map list
foreach (var num in ormMap)
{
Console.Write("{0} ", num);
}
Console.WriteLine();
// handle nulls
Console.WriteLine("{0} nulls encountered in dbQueryResults",
dbQueryResults.Where(nullableInt => !nullableInt.HasValue).Count());
}
Esempio Nullable<T>.GetValueOrDefault
In questo esempio, viene usato GetValueOrDefault(UTP) per specificare un valore predefinito all'esterno dei valori previsti restituiti da dbQueryResults.
private void MapQueryResults()
{
var dbQueryResults = new int?[] { 1, 2, null, 4 };
var nullFlag = int.MinValue;
var ormMap = dbQueryResults.Select(nullableInt => nullableInt.GetValueOrDefault(nullFlag));
// handle nulls
Console.WriteLine("'{0}' indicates a null database value.", nullFlag);
foreach (var num in ormMap)
{
Console.Write("{0} ", num);
}
Console.WriteLine();
}
Contenuto dell'articolo
Contenuto della sezione
Un metodo System.Linq.Enumerable viene chiamato su una raccolta vuota
I metodi di Enumerable Aggregate, Average, Last, Max, Min, First, Single e SingleOrDefault eseguono operazioni in una sequenza e restituiscono un singolo risultato.
Alcuni overload di questi metodi generano un'eccezione InvalidOperationException quando la sequenza è vuota (altri overload restituiscono null (Nothing in Visual Basic). SingleOrDefault genera InvalidOperationException anche quando la sequenza contiene più di un elemento.
Suggerimento
La maggior parte dei metodi Enumerable illustrati in questa sezione è in overload.Assicurarsi di comprendere il comportamento dell'overload scelto.
Messaggi di eccezione:
Metodi Aggregate, Average, Last, Max e Min | Metodi First e FirstOrDefault | Metodi Single e SingleOrDefault
Metodi Aggregate, Average, Last, Max e Min
- Altre informazioni: La sequenza non contiene elementi
Generazione di un'eccezione InvalidOperationException con Average
In questo esempio, il metodo seguente genera un'eccezione InvalidOperationException quando chiama il metodo Average perché l'espressione Linq restituisce una sequenza che non contiene elementi maggiori di 4.
private void FindAverageOfNumbersGreaterThan4()
{
var dbQueryResults = new[] { 1, 2, 3, 4 };
var avg = dbQueryResults.Where(num => num > 4).Average();
Console.WriteLine("The average value numbers greater than 4 in the returned records is {0}", avg);
}
Quando si usa uno di questi metodi senza verificare la presenza di una sequenza vuota, si presuppone implicitamente che la sequenza non sia vuota e che una sequenza vuota sia un'occorrenza imprevista. La generazione o il rilevamento dell'eccezione è appropriato quando si presuppone che la sequenza non sarà vuota.
Evitare un'eccezione InvalidOperationException causata da una sequenza vuota
Usare uno dei metodi Enumerable.Any per verificare se la sequenza è vuota.
Suggerimento
L'uso di Any può migliorare le prestazioni della verifica se la sequenza di cui calcolare la media può contenere un numero elevato di elementi o se l'operazione che genera la sequenza è onerosa.
private void FindAverageOfNumbersGreaterThan4()
{
var dbQueryResults = new[] { 1, 2, 3, 4 };
var moreThan4 = dbQueryResults.Where(num => num > 4);
if(moreThan4.Any())
{
var msgFormat = "The average value numbers greater than 4 in the returned records is {0}";
Console.WriteLine(msgFormat, moreThan4.Average());
}
else
{
// handle empty collection
Console.WriteLine("There are no values greater than 4 in the ecords.");
}
}
Contenuto dell'articolo
Contenuto della sezione
Metodi First e FirstOrDefault
First restituisce il primo elemento di una sequenza o genera un'eccezione InvalidOperationException se la sequenza è vuota. È possibile chiamare il metodo FirstOrDefault anziché First per restituire un valore specificato o predefinito anziché generare l'eccezione.
Nota
In .NET Framework i tipi hanno un concetto di valori predefiniti.Ad esempio, per i tipi di riferimento il valore predefinito è null, mentre per un tipo Integer è zero.Vedere Tabella dei valori predefiniti (Riferimenti per C#)
Generazione di un'eccezione InvalidOperationException con First
First è un metodo di ottimizzazione che restituisce il primo elemento di una sequenza che soddisfa una condizione specificata. Se non viene trovato un elemento che soddisfa la condizione, i metodi generano un'eccezione InvalidOperationException.
In questo esempio, il metodo First genera l'eccezione perché dbQueryResults non contiene un elemento maggiore di 4.
Messaggio di eccezione:
- Altre informazioni: La sequenza non contiene elementi corrispondenti
private void FindANumbersGreaterThan4()
{
var dbQueryResults = new[] { 1, 2, 3, 4 };
var firstNum = dbQueryResults.First(n=> n > 4);
var msgFormat = "{0} is an element of dbQueryResults that is greater than 4";
Console.WriteLine(msgFormat, firstNum);
}
Evitare un'eccezione con FirstOrDefault
È possibile usare i metodi FirstOrDefault al posto di First per verificare che la sequenza firstNum contenga almeno un elemento. Se la query non trova un elemento che soddisfa la condizione, restituisce un valore specificato o predefinito. È possibile controllare il valore restituito per determinare se verranno trovati elementi.
Nota
L'uso di FirstOrDefault può essere più complicato da implementare se il valore predefinito del tipo e un elemento valido nella sequenza.
private void FindANumbersGreaterThan4()
{
var dbQueryResults = new[] { 1, 2, 3, 4 };
// default(object) == null
var firstNum = dbQueryResults.FirstOrDefault(n => n > 4);
if (firstNum != 0)
{
var msgFormat = "{0} is an element of dbQueryResults that is greater than 4";
Console.WriteLine(msgFormat, firstNum);
}
else
{
// handle default case
Console.WriteLine("No element of dbQueryResults is greater than 4.");
}
}
Contenuto dell'articolo
Contenuto della sezione
Metodi Single e SingleOrDefault
I metodi Enumerable.Single restituiscono l'unico elemento di una sequenza o l'unico elemento di una sequenza che soddisfa un test specificato.
Se nella sequenza non sono presenti elementi o se è presente più di un elemento, il metodo genera un'eccezione InvalidOperationException.
È possibile usare SingleOrDefault per restituire un valore specificato o predefinito anziché generare l'eccezione quando la sequenza non contiene elementi. Tuttavia, SingleOrDefault genererà comunque un'eccezione InvalidOperationException quando la sequenza contiene più di un elemento che corrisponde al predicato di selezione.
Nota
In .NET Framework i tipi hanno un concetto di valori predefiniti.Ad esempio, per i tipi di riferimento il valore predefinito è null, mentre per un tipo Integer è zero.Vedere Tabella dei valori predefiniti (Riferimenti per C#)
Generazione di eccezioni InvalidOperationException con Single
In questo esempio, singleObject genera un'eccezione InvalidOperationException perché dbQueryResults non contiene un elemento maggiore di 4.
Messaggio di eccezione:
- Altre informazioni: La sequenza non contiene elementi corrispondenti
private void FindTheOnlyNumberGreaterThan4()
{
var dbQueryResults = new[] { (object)1, (object)2, (object)3, (object)4 };
var singleObject = dbQueryResults.Single(obj => (int)obj > 4);
// display results
var msgFormat = "{0} is the only element of dbQueryResults that is greater than 4";
Console.WriteLine(msgFormat, singleObject);
}
Generazione di eccezioni InvalidOperationException con Single o SingleOrDefault
In questo esempio, singleObject genera un'eccezione InvalidOperationException perché dbQueryResults contiene più di un elemento maggiore di 2.
Messaggio di eccezione:
- Altre informazioni: La sequenza contiene più di un elemento corrispondente
private void FindTheOnlyNumberGreaterThan2()
{
var dbQueryResults = new[] { (object)1, (object)2, (object)3, (object)4 };
var singleObject = dbQueryResults.SingleOrDefault(obj => (int)obj > 2);
if (singleObject != null)
{
var msgFormat = "{0} is the only element of dbQueryResults that is greater than 2";
Console.WriteLine(msgFormat, singleObject);
}
else
{
// handle empty collection
Console.WriteLine("No element of dbQueryResults is greater than 2.");
}
}
Evitare le eccezioni InvalidOperationException con Single
L'uso di Single e SingleOrDefault serve anche da documentazione delle intenzioni. Single implica fortemente la restituzione di un solo risultato dalla condizione. SingleOrDefault dichiara che si prevede venga restituito uno o zero risultati ma non di più. Quando queste condizioni non sono valide, la generazione o il rilevamento dell'eccezione InvalidOperationException è appropriato. Tuttavia, se si prevede il verificarsi di condizioni non valide con una certa frequenza, è consigliabile usare altri metodi Enumerable, ad esempio First o Where, per generare i risultati.
Durante lo sviluppo, è possibile usare uno dei metodi Assert per verificare i presupposti. In questo esempio, il codice evidenziato provoca l'interruzione del debugger e visualizza una finestra di dialogo di asserzione durante lo sviluppo. L'asserzione viene rimossa nel codice di rilascio e verrà generato un metodo Single se i risultati non sono validi.
Nota
Se si usa Take``1 e si imposta il relativo parametro count su 2, si limita la sequenza restituita a due elementi al massimo.Questa sequenza include tutti i casi che è necessario verificare (0, 1 e più di 1 elemento) e può migliorare le prestazioni del controllo quando la sequenza può contenere un numero elevato di elementi o se l'operazione che genera la sequenza è onerosa.
private void FindTheOnlyNumberGreaterThan4()
{
var dbQueryResults = new[] { (object)1, (object)2, (object)3, (object)4 };
var moreThan4 = dbQueryResults.Where(obj => (int)obj > 4).Take(2);
System.Diagnostics.Debug.Assert(moreThan4.Count() == 1,
String.Format("moreThan4.Count() == 1; Actual count: {0}", moreThan4.Count()));
// do not handle exceptions in release code
Console.WriteLine("{0} is the only element of dbQueryResults that is greater than 4",
moreThan4.Single());
}
Se si desidera evitare l'eccezione, ma comunque gestire gli stati non validi nel codice di rilascio, è possibile modificare la tecnica sopra descritta. In questo esempio, il metodo risponde al numero di elementi restituiti da moreThan2 nell'istruzione switch.
private void FindTheOnlyNumberGreaterThan2()
{
var dbQueryResults = new[] { (object)1, (object)2, (object)3, (object)4 };
var moreThan2 = dbQueryResults.TakeWhile(obj => (int)obj > 2).Take(2);
switch(moreThan2.Count())
{
case 1:
// success
var msgFormat = "{0} is the only element of dbQueryResults that is greater than 2";
Console.WriteLine(msgFormat, moreThan2.Single());
break;
case 0:
// handle empty collection
Console.WriteLine("No element of the dbQueryResults are greater than 4.");
break;
default: // count > 1
// handle more than one element
Console.WriteLine("More than one element of dbQueryResults is greater than 4");
break;
}
}
Contenuto dell'articolo
Contenuto della sezione
Articoli correlati
Linee guida di progettazione delle eccezioni (Linee guida per la progettazione di .NET Framework)
Gestione e generazione di eccezioni (Concetti di base sulle applicazioni .NET Framework)
Procedura: Ricevere notifiche di eccezioni first-chance (Guida di sviluppo per .NET Framework)
Procedura: Gestire le eccezioni in una query PLINQ (Guida di sviluppo per .NET Framework)
Eccezioni in thread gestiti (Guida di sviluppo per .NET Framework)
Eccezioni e gestione delle eccezioni (Guida per programmatori C#)
Istruzioni di gestione delle eccezioni (Riferimenti per C#)
.Istruzione Try...Catch...Finally (Visual Basic)
Gestione delle eccezioni (Task Parallel Library)
Gestione delle eccezioni (debug)
Procedura dettagliata: Gestione di un'eccezione di concorrenza (Accesso ai dati in Visual Studio)
Procedura: Gestire gli errori e le eccezioni che si verificano con il data binding (Windows Forms)
Gestione di eccezioni nelle app di rete (XAML) (Windows)
In questo articolo