Skip to content

Commit 452b9ef

Browse files
authored
System.AggregateException F# snippets (dotnet#7407)
* Add F# snippets for System.AggregateException * Update AggregateException.xml * Update exception1.fs
1 parent 8307ab1 commit 452b9ef

File tree

8 files changed

+250
-0
lines changed

8 files changed

+250
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// <Snippet1>
2+
open System
3+
open System.IO
4+
open System.Threading.Tasks
5+
6+
let getAllFiles str =
7+
// Should throw an UnauthorizedAccessException exception.
8+
System.IO.Directory.GetFiles(str, "*.txt", System.IO.SearchOption.AllDirectories)
9+
10+
// Get a folder path whose directories should throw an UnauthorizedAccessException.
11+
let path =
12+
let directory =
13+
Environment.SpecialFolder.UserProfile
14+
|> Environment.GetFolderPath
15+
|> Directory.GetParent
16+
directory.FullName
17+
18+
// Use this line to throw an exception that is not handled.
19+
// let task1 = Task<string []>.Factory.StartNew(fun () -> raise (IndexOutOfRangeException()) )
20+
let task1 = Task.Factory.StartNew(fun () -> getAllFiles (path))
21+
22+
let execute () =
23+
try
24+
task1.Wait()
25+
with
26+
| :? UnauthorizedAccessException -> printfn "Caught unauthorized access exception-await behavior"
27+
| :? AggregateException as ae ->
28+
printfn "Caught aggregate exception-Task.Wait behavior"
29+
30+
ae.Handle (fun x ->
31+
match x with
32+
| :? UnauthorizedAccessException ->
33+
printfn "You do not have permission to access all folders in this path."
34+
printfn "See your network administrator or try another path."
35+
true
36+
| _ -> false)
37+
printfn $"""task1 Status: {if task1.IsCompleted then "Completed," else ""}{task1.Status}"""
38+
39+
execute ()
40+
41+
// The example displays the following output if the file access task is run:
42+
// You do not have permission to access all folders in this path.
43+
// See your network administrator or try another path.
44+
// task1 Status: Completed,Faulted
45+
// It displays the following output if the second task is run:
46+
// Unhandled exception. System.AggregateException: One or more errors occurred. (Index was outside the bounds of the array.) (Index was outside the bounds of the array.)
47+
// ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.
48+
49+
// at System.Threading.Tasks.Task`1.InnerInvoke()
50+
// at System.Threading.Tasks.Task.<>c.<.cctor>b__277_0(Object obj)
51+
// at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
52+
// --- End of stack trace from previous location ---
53+
// at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
54+
// at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
55+
// --- End of inner exception stack trace ---
56+
// at System.AggregateException.Handle(Func`2 predicate)
57+
// at <StartupCode$exception1>.$Exception1.main@()
58+
// </Snippet1>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net5.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Compile Include="exception1.fs" />
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module flatten2
2+
// <Snippet22>
3+
open System
4+
open System.Threading.Tasks
5+
6+
type CustomException(message) =
7+
inherit Exception(message)
8+
9+
let task1 =
10+
Task.Factory.StartNew (fun () ->
11+
let child1 =
12+
Task.Factory.StartNew(
13+
(fun () ->
14+
let child2 =
15+
Task.Factory.StartNew(
16+
(fun () -> raise (CustomException "Attached child2 faulted,")),
17+
TaskCreationOptions.AttachedToParent
18+
)
19+
raise (CustomException "Attached child1 faulted.")),
20+
TaskCreationOptions.AttachedToParent
21+
)
22+
()
23+
)
24+
25+
try
26+
task1.Wait()
27+
with
28+
| :? AggregateException as ae ->
29+
for e in ae.Flatten().InnerExceptions do
30+
if e :? CustomException then
31+
printfn "%s" e.Message
32+
else
33+
reraise()
34+
35+
// The example displays the following output:
36+
// Attached child1 faulted.
37+
// Attached child2 faulted.
38+
// </Snippet22>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module handlemethod2
2+
// <Snippet16>
3+
open System
4+
open System.Threading.Tasks
5+
6+
type CustomException(message) =
7+
inherit Exception(message)
8+
9+
let task1 =
10+
Task.Run(fun () -> raise (CustomException "This exception is expected!"))
11+
12+
try
13+
task1.Wait()
14+
with
15+
| :? AggregateException as ae ->
16+
// Call the Handle method to handle the custom exception,
17+
// otherwise rethrow the exception.
18+
ae.Handle (fun ex ->
19+
if ex :? CustomException then
20+
printfn $"{ex.Message}"
21+
22+
ex :? CustomException)
23+
24+
// The example displays the following output:
25+
// This exception is expected!
26+
// </Snippet16>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module taskexceptions
2+
// <snippet12>
3+
open System
4+
open System.IO
5+
open System.Threading.Tasks
6+
7+
let getAllFiles path =
8+
let task1 =
9+
Task.Run(fun () -> Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories))
10+
11+
try
12+
task1.Result
13+
with
14+
| :? AggregateException as ae ->
15+
ae.Handle (fun x ->
16+
// Handle an UnauthorizedAccessException
17+
if x :? UnauthorizedAccessException then
18+
printfn "You do not have permission to access all folders in this path."
19+
printfn "See your network administrator or try another path."
20+
21+
x :? UnauthorizedAccessException)
22+
23+
Array.empty
24+
25+
// This should throw an UnauthorizedAccessException.
26+
try
27+
let files = getAllFiles @"C:\"
28+
29+
if not (isNull files) then
30+
for file in files do
31+
printfn $"{file}"
32+
with
33+
| :? AggregateException as ae ->
34+
for ex in ae.InnerExceptions do
35+
printfn $"{ex.GetType().Name}: {ex.Message}"
36+
37+
printfn ""
38+
39+
// This should throw an ArgumentException.
40+
try
41+
for s in getAllFiles "" do
42+
printfn $"{s}"
43+
with
44+
| :? AggregateException as ae ->
45+
for ex in ae.InnerExceptions do
46+
printfn $"{ex.GetType().Name}: {ex.Message}"
47+
48+
// The example displays the following output:
49+
// You do not have permission to access all folders in this path.
50+
// See your network administrator or try another path.
51+
//
52+
// ArgumentException: The path is empty. (Parameter 'path')
53+
// </snippet12>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
module taskexceptions2
2+
// <snippet13>
3+
open System
4+
open System.IO
5+
open System.Threading.Tasks
6+
7+
let executeTasks () =
8+
// Assume this is a user-entered String.
9+
let path = @"C:\"
10+
11+
let tasks =
12+
[| Task.Run (fun () ->
13+
// This should throw an UnauthorizedAccessException.
14+
Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories))
15+
:> Task
16+
Task.Run (fun () ->
17+
if path = @"C:\" then
18+
raise (ArgumentException "The system root is not a valid path.")
19+
20+
[| ".txt"; ".dll"; ".exe"; ".bin"; ".dat" |])
21+
:> Task
22+
Task.Run(fun () -> raise (NotImplementedException "This operation has not been implemented")) |]
23+
24+
try
25+
Task.WaitAll(tasks)
26+
with
27+
| :? AggregateException as ae -> raise (ae.Flatten())
28+
29+
try
30+
executeTasks ()
31+
with
32+
| :? AggregateException as ae ->
33+
for e in ae.InnerExceptions do
34+
printfn $"{e.GetType().Name}:\n {e.Message}"
35+
36+
// The example displays the following output:
37+
// UnauthorizedAccessException:
38+
// Access to the path 'C:\Documents and Settings' is denied.
39+
// ArgumentException:
40+
// The system root is not a valid path.
41+
// NotImplementedException:
42+
// This operation has not been implemented.
43+
// </Snippet13>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net5.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Compile Include="flatten2.fs" />
10+
<Compile Include="taskexceptions2.fs" />
11+
<Compile Include="handlemethod2.fs" />
12+
<Compile Include="taskexceptions.fs" />
13+
</ItemGroup>
14+
15+
</Project>

xml/System/AggregateException.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
The following example catches the <xref:System.AggregateException> exception and calls the <xref:System.AggregateException.Handle%2A> method to handle each exception it contains. Compiling and running the example with the first `task1` variable should result in an <xref:System.AggregateException> object that contains an <xref:System.UnauthorizedAccessException> exception. Commenting out that line, uncommenting the second `task1` variable, and compiling and running the example produces an <xref:System.AggregateException> object that contains an <xref:System.IndexOutOfRangeException> exception.
7272
7373
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/system.aggregateexception.class/cs/exception1.cs" id="Snippet1":::
74+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/system.aggregateexception.class/fs/exception1.fs" id="Snippet1":::
7475
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.aggregateexception.class/vb/exception1.vb" id="Snippet1":::
7576
7677
]]></format>
@@ -548,11 +549,13 @@
548549
In the following example, nested <xref:System.AggregateException> instances are flattened and handled in just one loop.
549550
550551
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_Misc/tpl_exceptions/cs/flatten2.cs" id="Snippet22":::
552+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_Misc/tpl_exceptions/fs/flatten2.fs" id="Snippet22":::
551553
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_Misc/tpl_exceptions/vb/flatten2.vb" id="Snippet22":::
552554
553555
You can also use the <xref:System.AggregateException.Flatten%2A?displayProperty=nameWithType> method to rethrow the inner exceptions from multiple <xref:System.AggregateException> instances thrown by multiple tasks in a single <xref:System.AggregateException> instance, as the following example shows.
554556
555557
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_Misc/tpl_exceptions/cs/taskexceptions2.cs" id="Snippet13":::
558+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_Misc/tpl_exceptions/fs/taskexceptions2.fs" id="Snippet13":::
556559
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_Misc/tpl_exceptions/vb/taskexceptions2.vb" id="Snippet13":::
557560
558561
]]></format>
@@ -712,11 +715,13 @@
712715
Ordinarily, an exception handler that catches an <xref:System.AggregateException> exception uses a `foreach` loop (in C#) or `For Each` loop (in Visual Basic) to handle each exception in its <xref:System.AggregateException.InnerExceptions%2A> collection. Instead, the following example uses the <xref:System.AggregateException.Handle%2A> method to handle each exception, and only re-throws exceptions that are not `CustomException` instances.
713716
714717
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_Misc/tpl_exceptions/cs/handlemethod2.cs" id="Snippet16":::
718+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_Misc/tpl_exceptions/fs/handlemethod2.fs" id="Snippet16":::
715719
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_Misc/tpl_exceptions/vb/handlemethod2.vb" id="Snippet16":::
716720
717721
The following is a more complete example that uses the <xref:System.AggregateException.Handle%2A> method to provide special handling for an <xref:System.UnauthorizedAccessException> when enumerating files.
718722
719723
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_Misc/tpl_exceptions/cs/taskexceptions.cs" id="Snippet12":::
724+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_Misc/tpl_exceptions/fs/taskexceptions.fs" id="Snippet12":::
720725
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_Misc/tpl_exceptions/vb/taskexceptions.vb" id="Snippet12":::
721726
722727
]]></format>

0 commit comments

Comments
 (0)