finish lecture 14, add snippets and css

main
borb 3 days ago
parent 07494d7428
commit 327c710e51

@ -8,3 +8,23 @@
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1rem; gap: 1rem;
} }
.columns12 {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 1rem;
}
.columns21 {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1rem;
}
.centered {
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.tableborderless td, th {
border: none!important;
border-collapse: collapse;
}

@ -107,6 +107,15 @@
"</div>", "</div>",
] ]
}, },
"marp centered" : {
"scope": "markdown",
"prefix": "centered",
"body" : [
"<div class='centered'>",
"$0",
"</div>",
]
},
"marp footer" : { "marp footer" : {
"scope": "markdown", "scope": "markdown",
"prefix": "footer", "prefix": "footer",

File diff suppressed because one or more lines are too long

@ -1,111 +1,101 @@
# Exceptions, ---
Threads and Tasks marp: true
paginate: true
math: mathjax
theme: buutti
title: 14. Exceptions, Threads and Tasks
---
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_0.png) # Exceptions, Threads and Tasks
--- <!-- headingDivider: 5 -->
<!-- class: invert -->
# Exceptions ## Exceptions
* Exceptions are problems that occur during the lifetime of the program * Exceptions are problems that occur during the lifetime of the program
* Typical exceptions are IndexOutOfRangeException and NullReferenceException * Typical exceptions are `IndexOutOfRangeException` and `NullReferenceException`
* IndexOutOfRangeException occurs when trying to access an element of an object using an index greater than the number of elements in that object * `IndexOutOfRangeException` occurs when trying to access an element of an object using an index greater than the number of elements in that object
* NullReferenceException occurs when trying to reference a variable that has not been assigned a value * `NullReferenceException` occurs when trying to reference a variable that has not been assigned a value
# Exceptions (continued) ## Checking for exceptions
* There should be some kind of system to check for these problems so that even if they do occur, the application does not crash * There should be some kind of system to check for these problems so that even if they do occur, the application does not crash
* For example, if a user tries to read from a file that does not exist, the user should be given an informative error message instead of closing the application * For example, if a user tries to read from a file that does not exist, the user should be given an informative error message instead of closing the application
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_1.png)
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_2.png) <div class='tableborderless'>
| ❌ | ✅ |
| ---------- | --------- |
| ![width:550px](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_2.png) | ![width:550px](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_1.png) |
# try - catch </div>
Wrap the code that could result in an exception in a __try __ block
Wrap the code that should execute if an exception occurs in a __catch __ block ## Try-catch
* Wrap the code that could result in an exception in a *__try__* block
* Wrap the code that should execute if an exception occurs in a *__catch__* block
```csharp
string path = @"C:\\Users\\Public\\TestFolder\\WriteText.txt"; string path = @"C:\\Users\\Public\\TestFolder\\WriteText.txt";
try try
{ {
string text = System.IO.File.ReadAllText(path); string text = System.IO.File.ReadAllText(path);
} }
catch(DirectoryNotFoundException e) catch(DirectoryNotFoundException e)
{ {
Console.WriteLine($"The path {path} does not exist."); Console.WriteLine($"The path {path} does not exist.");
} }
```
# throw ## Throw
__throw __ - keyword results in the exception that is caught in the catch block
This can be used if you want to execute some code before stopping the execution of the program * The *__throw__* keyword results in the exception that is caught in the catch block
* Can be used to execute some code before stopping the execution of the program
```csharp
string path = @"C:\\Users\\Public\\TestFolder\\WriteText.txt"; string path = @"C:\\Users\\Public\\TestFolder\\WriteText.txt";
try try
{ {
string text = System.IO.File.ReadAllText(path); string text = System.IO.File.ReadAllText(path);
} }
catch (IOException e) catch (IOException e)
{ {
Console.WriteLine("An exception occurred."); Console.WriteLine("An exception occurred.");
Console.WriteLine("Logging exception information..."); Console.WriteLine("Logging exception information...");
Console.WriteLine($"Exception: {e.Message}"); Console.WriteLine($"Exception: {e.Message}");
throw; throw;
} }
```
# finally ## Finally
__finally __ block executes after try-catch regardless of whether an exception occurred or not
This is useful for closing unmanaged objects like database connections and file streams * *__finally__* block executes after a try-catch regardless of whether an exception occurred or not
* Useful for closing unmanaged objects like database connections or file streams
```csharp
try try
{ {
// Open a database connection or file stream // Open a database connection or file stream
} }
catch (SystemException e) catch (SystemException e)
{ {
// Do this if connection / stream fails // Do this if connection / stream fails
} }
finally finally
{ {
// Release the unmanaged resources from memory // Release the unmanaged resources from memory
} }
```
## Exercise 1: Debugging Exceptions
# Exercise 1: Debugging Exceptions <!-- _backgroundColor: #29366f -->
Create a savings calculator which asks the user for a target amount of money the user is aiming for (in integers), and the users monthly salary. For parsing, use the int.Parse() method instead of int.TryParse(). Create a savings calculator which asks the user for a target amount of money the user is aiming for (in integers), and the users monthly salary. For parsing, use the int.Parse() method instead of int.TryParse().
@ -117,129 +107,114 @@ Try your program with different user inputs. Try to intentionally break your pro
Handle the exceptions with exception handling, and inform the user of each exception with an appropriate message. Handle the exceptions with exception handling, and inform the user of each exception with an appropriate message.
# Threads ## Threads
* You might have time consuming functionality in your program, like * You might have time consuming functionality in your program, like...
* heavy algorithms and mathematical calculations, or * heavy algorithms and mathematical calculations
* reading a large amount of data from a file * reading a large amount of data from a file
* You could also have some continuous stream of data being read, like * You could also have some continuous stream of data being read, like...
* serial signal * serial signal
* In case of time consuming methods, it might be a bad idea to wait for the execution to finish before continuing the main program * In case of time consuming methods, it might be a bad idea to wait for the execution to finish before continuing the main program
* This would show up to the user as the program being stuck * This would show up to the user as the program being stuck
* At the very least, there could be some progress bar to indicate that the program hasn't crashed * At the very least, there could be some progress bar to indicate that the program hasn't crashed
* In the case of continuous execution, there needs to be some way to read the stream and execute the main program at the same time * In the case of continuous execution, there needs to be some way to read the stream and execute the main program at the same time
# Threads (continued) ## Threads (continued)
.NET supports __multithreading __ and classes to add new threads are included in the base class library
* .NET supports *__multithreading__* and classes to add new threads are included in the base class library
```csharp
using System.Threading; using System.Threading;
```
* Separate tasks can be executed simultaneously on separate *__threads__*
* Separate threads run on different cores in the processor
* All threads have access to the resources allocated to your program
Separate tasks can be executed simultaneously on separate __threads__ ---
Separate threads run on different cores in the processor
All threads have access to the resources allocated to your program
Initialize a ThreadStart object with the method to be threaded as the argument:
* Initialize a `ThreadStart` object with the method to be threaded as the argument:
```csharp
public static void PrintInteger() public static void PrintInteger()
... ...
ThreadStart printIntegerStart = new ThreadStart(PrintInteger); ThreadStart printIntegerStart = new ThreadStart(PrintInteger);
```
Initialize a Thread object with the ThreadStart object set as the argument, and start the new thread with Thread.Start() method: * Initialize a `Thread` object with the `ThreadStart` object set as the argument, and start the new thread with `Thread.Start()` method:
```csharp
Thread printIntegerThread = new Thread(printIntegerStart); Thread printIntegerThread = new Thread(printIntegerStart);
printIntegerThread.Start(); printIntegerThread.Start();
```
# Threads - Example ## Thread example
class Program <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program
{ {
public static void PrintInteger() public static void PrintInteger()
{ {
Console.WriteLine("Thread started."); Console.WriteLine("Thread started.");
int val = 0; int val = 0;
while (true) while (true)
{ {
Thread.Sleep(100); Thread.Sleep(100);
Console.WriteLine("Current value: " + val); Console.WriteLine("Current value: " + val);
++val; ++val;
} }
} }
static void Main(string[] args) static void Main(string[] args)
{ {
ThreadStart printIntegerStart = new ThreadStart(PrintInteger); ThreadStart printIntegerStart = new ThreadStart(PrintInteger);
Console.WriteLine("Starting thread..."); Console.WriteLine("Starting thread...");
Thread printIntegerThread = new Thread(printIntegerStart); Thread printIntegerThread = new Thread(printIntegerStart);
printIntegerThread.Start(); printIntegerThread.Start();
Console.WriteLine("Main thread continuing."); Console.WriteLine("Main thread continuing.");
} }
} }
```
</div>
<div markdown='1'>
The PrintInteger method prints a value, waits for 0.1sec, increases the value, prints it again and so on The method prints a value, waits for $0.1\,\mathrm{s}$, increases the value, prints it again, etc.
The method keeps executing indefinitely, but the main thread continues execution as well The method keeps executing indefinitely, but the main thread continues execution as well!
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_3.png) ![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_3.png)
# Threads (continued) </div>
</div>
You can create as many threads as you like: ## Threads (continued)
ThreadStart printIntegerStart = new ThreadStart(PrintInteger); * You can create as many threads as you like:
```csharp
ThreadStart printIntegerStart = new ThreadStart(PrintInteger);
Console.WriteLine("Starting thread..."); Console.WriteLine("Starting thread...");
Thread printIntegerThread = new Thread(printIntegerStart); Thread printIntegerThread = new Thread(printIntegerStart);
printIntegerThread.Start(); printIntegerThread.Start();
Thread printIntegerThread2 = new Thread(printIntegerStart); Thread printIntegerThread2 = new Thread(printIntegerStart);
printIntegerThread2.Start(); printIntegerThread2.Start();
Thread printIntegerThread3 = new Thread(printIntegerStart); Thread printIntegerThread3 = new Thread(printIntegerStart);
printIntegerThread3.Start(); printIntegerThread3.Start();
```
# Exercise 2: Threaded Loading ## Exercise 2: Threaded Loading
<!-- _backgroundColor: #29366f -->
Create a method public static void LoadData() which simulates loading resources by printing progress from 0% to 100%. Increase the progress in a loop with 1% increments. Use the Thread.Sleep() method to wait 10 ms between each increment. Create a method `public static void LoadData()` which simulates loading resources by printing progress from $0 \%$ to $100 \%$. Increase the progress in a loop with $1 \%$ increments. Use the `Thread.Sleep()` method to wait $10\,\mathrm{ms}$ between each increment.
Create a main loop where each time the user presses enter, the LoadData() method is executed on a separate thread. Create a main loop where each time the user presses enter, the `LoadData()` method is executed on a separate thread.
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_4.png) ![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_4.png)
--- <!-- _footer: Näytä ekstrana, miten tämä tehdään käyttäen luokan metodia eri luokan arvoilla -->
Näytä ekstrana, miten tämä tehdään käyttäen luokan metodia eri luokan arvoilla
# Tasks ## Tasks
* In some cases you want to continue working on some tasks while others are queued to be executed * In some cases you want to continue working on some tasks while others are queued to be executed
* For example, after sending a server request, you might want to begin some tasks immediately and others only after a response has been received * For example, after sending a server request, you might want to begin some tasks immediately and others only after a response has been received
@ -248,71 +223,63 @@ Näytä ekstrana, miten tämä tehdään käyttäen luokan metodia eri luokan ar
# Tasks - Continued # Tasks - Continued
To create an asynchronous method, assign it with the async keyword. It is good practice to end the method name with Async * To create an asynchronous method, assign it with the async keyword. It is good practice to end the method name with Async
* The method should return a value of the type that is specified in the angled brackets (if your task doesn't return a value, leave the brackets out)
The method should return a value of the type that is specified in the angled brackets (if your task doesn't return a value, leave the brackets out) * Inside the method, call an asynchronous method with the await keyword:
```csharp
Inside the method, call an asynchronous method with the await keyword:
static async Task<int> MyMethodAsync() static async Task<int> MyMethodAsync()
{ {
byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/"); byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/");
return content.Length; return content.Length;
} }
```
This method can now be called asynchronously: * This method can now be called asynchronously:
```csharp
Task<int> myMethodResult = MyMethodAsync(); Task<int> myMethodResult = MyMethodAsync();
```
# Tasks - Example ## Tasks example
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_5.png)
class Program <div class='columns21' markdown='1'>
<div markdown='1'>
```csharp
class Program
{ {
static async Task<string> GetResultAsync() static async Task<string> GetResultAsync()
{ {
int waitTime = 5000; int waitTime = 5000;
await Task.Delay(waitTime);
await Task.Delay(waitTime); // Replace this with your time consuming async functionality // Replace this with your time consuming async functionality
return new string(
return new string($"The task took {waitTime / 1000} seconds to finish."); $"The task took {waitTime / 1000} seconds to finish."
);
} }
static void Main(string[] args) static void Main(string[] args)
{ {
Console.WriteLine("Starting operation..."); Console.WriteLine("Starting operation...");
Task<string> resultTask = GetResultAsync(); Task<string> resultTask = GetResultAsync();
Console.WriteLine("Operation has been started."); Console.WriteLine("Operation has been started.");
Console.WriteLine("In the meantime, tell me something nice: "); Console.WriteLine("In the meantime, tell me something nice: ");
string somethingNice = Console.ReadLine(); string somethingNice = Console.ReadLine();
resultTask.Wait(); // Wait for the task to complete resultTask.Wait(); // Wait for the task to complete
Console.WriteLine(resultTask.Result); Console.WriteLine(resultTask.Result);
Console.ReadKey(); Console.ReadKey();
} }
} }
```
</div>
<div markdown='1'>
![](imgs/14%20Exceptions%2C%20Threads%20and%20Tasks_5.png)
</div>
</div>
# Exercise 3: Asynchronous Loading ## Exercise 3: Asynchronous Loading
<!-- _backgroundColor: #29366f -->
Re-create the exercise 2, but instead of using separate threads for "loading the data", use an asynchronous method LoadDataAsync() Re-create the exercise 2, but instead of using separate threads for "loading the data", use an asynchronous method `LoadDataAsync()`

Loading…
Cancel
Save