diff --git a/Tasks/TasksInConsole/TasksInConsole.sln b/Tasks/TasksInConsole/TasksInConsole.sln
new file mode 100644
index 0000000..08e12c0
--- /dev/null
+++ b/Tasks/TasksInConsole/TasksInConsole.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.2037
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TasksInConsole", "TasksInConsole\TasksInConsole.csproj", "{74FA56F8-DC5F-4DBE-AC49-3A770A5D1745}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {74FA56F8-DC5F-4DBE-AC49-3A770A5D1745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {74FA56F8-DC5F-4DBE-AC49-3A770A5D1745}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {74FA56F8-DC5F-4DBE-AC49-3A770A5D1745}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {74FA56F8-DC5F-4DBE-AC49-3A770A5D1745}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {90A07E03-AB2D-45BE-A1BF-B7AF2FBBB59F}
+ EndGlobalSection
+EndGlobal
diff --git a/Tasks/TasksInConsole/TasksInConsole/Program.cs b/Tasks/TasksInConsole/TasksInConsole/Program.cs
new file mode 100644
index 0000000..bf9a4ee
--- /dev/null
+++ b/Tasks/TasksInConsole/TasksInConsole/Program.cs
@@ -0,0 +1,767 @@
+using System;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace TasksInConsole
+{
+ class Program
+ {
+ #region Private Members
+
+ ///
+ /// The event finished callback for the Thread event example
+ ///
+ private static event Action EventFinished = () => { };
+
+ ///
+ /// Whether to run the thread examples
+ ///
+ private static bool RunThreadExamples = false;
+
+ #endregion
+
+ static void Main(string[] args)
+ {
+ // Log it
+ Log("Hello World!");
+
+ //
+ // Author: Luke Malpass
+ // License: MIT
+ // Support Me: https://www.patreon.com/angelsix
+ // Source Code: http://www.github.com/angelsix/youtube/Tasks
+ // Website: http://www.angelsix.com
+ // Contact: contact@angelsix.com
+ //
+ //
+ // What is Asynchronous
+ // ======================
+ //
+ // Asynchronous is if you start something, and don't wait while its happening.
+ // It literally means to not occur at the same time.
+ //
+ // This means not that our code returns early, but rather it doesn't sit there
+ // blocking the code while it waits (doesn't block the thread)
+ //
+
+ //
+ // Issues with Threads
+ // =====================
+ //
+ // Threads are asynchronous, as they naturally do something while the calling thread
+ // that made it doesn't wait for it.
+ //
+
+ #region Threads are asynchronous
+
+ if (RunThreadExamples)
+ {
+ // Log it
+ Log("Before first thread");
+
+ // Start new thread
+ new Thread(() =>
+ {
+ // Sleep a little
+ Thread.Sleep(500);
+
+ // Log it
+ Log("Inside first thread");
+
+ }).Start();
+
+ // Log it
+ Log("After first thread");
+
+ // Wait for work to finish
+ Thread.Sleep(1000);
+
+ Console.WriteLine("---------------------------------------------");
+ }
+
+ #endregion
+
+ // What's the issue with Threads?
+ //
+ // 1. Expensive to make
+ // 2. Not natural to be able to resume after a thread has finished to do something
+ // related to the thread that created it
+ //
+ // Issue 1 was solved with a ThreadPool. However issue 2 is still an issue for threads,
+ // and is one reason why Tasks were made.In order to resume work after some
+ // asynchronous operation has occurred we could with a Thread:
+ //
+ // 1. Block your code waiting for it (no better than just doing it on same thread)
+ //
+
+ #region Blocking Wait
+
+ if (RunThreadExamples)
+ {
+ // Log it
+ Log("Before blocking thread");
+
+ // Create new thread
+ var blockingThread = new Thread(() =>
+ {
+ // Sleep a little
+ Thread.Sleep(500);
+
+ // Log it
+ Log("Inside blocking thread");
+ });
+
+ // Start thread
+ blockingThread.Start();
+
+ // Block and wait
+ blockingThread.Join();
+
+ // Log
+ Log("After blocking thread");
+ Console.WriteLine("---------------------------------------------");
+ }
+
+ #endregion
+
+ // 2. Constantly poll for completion, waiting for a bool flag to say done (inefficient, slow)
+
+ #region Polling Wait
+
+ if (RunThreadExamples)
+ {
+ // Log it
+ Log("Before polling thread");
+
+ // Create poll flag
+ var pollComplete = false;
+
+ // Create thread
+ var pollingThread = new Thread(() =>
+ {
+ // Log it
+ Log("Inside polling thread");
+
+ // Sleep a little
+ Thread.Sleep(500);
+
+ // Set flag complete
+ pollComplete = true;
+ });
+
+ // Start thread
+ pollingThread.Start();
+
+ // Poll for completion
+ while (!pollComplete)
+ {
+ // Log it
+ Log("Polling....");
+
+ // Sleep a little
+ Thread.Sleep(100);
+ }
+
+ // Log it
+ Log("After polling thread");
+ Console.WriteLine("---------------------------------------------");
+ }
+
+ #endregion
+
+ // 3. Event-based callbacks (lose the calling thread on callback, and causes nesting)
+
+ #region Event-based Wait
+
+ if (RunThreadExamples)
+ {
+ // Log it
+ Log("Before event thread");
+
+ // Create thread
+ var eventThread = new Thread(() =>
+ {
+ // Log it
+ Log("Inside event thread");
+
+ // Sleep a little
+ Thread.Sleep(500);
+
+ // Fire completed event
+ EventFinished();
+ });
+
+ // Hook into callback event
+ EventFinished += () =>
+ {
+ // Log it
+ Log("Event thread callback on complete");
+ };
+
+ // Start thread
+ eventThread.Start();
+
+ // Log it
+ Log("After event thread");
+
+ // Wait for work to finish
+ Thread.Sleep(1000);
+
+ Console.WriteLine("---------------------------------------------");
+ }
+
+ #endregion
+
+ #region Event-based Wait Method
+
+ if (RunThreadExamples)
+ {
+ // Log it
+ Log("Before event method thread");
+
+ // Call event callback style method
+ EventThreadCallbackMethod(() =>
+ {
+ // Log it
+ Log("Event thread callback on complete");
+ });
+
+ // Log it
+ Log("After event method thread");
+
+ // Wait for work to finish
+ Thread.Sleep(1000);
+
+ Console.WriteLine("---------------------------------------------");
+ }
+
+ #endregion
+
+ //
+ // However that makes every time we want to do something asynchronous a lot of code
+ // and not easy to follow.
+ //
+
+ //
+ // What is a Task
+ // ================
+ //
+ // A Task encapsulates the promise of an operation completing in the future
+ //
+
+ //
+ // Tasks, Async and Await
+ // ========================
+ //
+ // Async in C# is mainly 2 words. async and await
+ //
+ // The point is to allow easy and clean asynchronous code to be written without complex or messy code.
+ //
+
+ #region Sync vs Async Method
+
+ // Log it
+ Log("Before sync thread");
+
+ // Website to fetch
+ var website = "http://www.google.co.uk";
+
+ // Download the string
+ WebDownloadString(website);
+
+ // Log it
+ Log("After sync thread");
+
+ Console.WriteLine("---------------------------------------------");
+
+ // Log it
+ Log("Before async thread");
+
+ // Download the string asynchronously
+ var downloadTask = WebDownloadStringAsync(website);
+
+ // Log it
+ Log("After async thread");
+
+ // Wait for task to complete
+ downloadTask.Wait();
+
+ Console.WriteLine("---------------------------------------------");
+
+ var task = Task.Run(async () =>
+ {
+ // Log it
+ Log("Before async await thread");
+
+ // Download the string asynchronously
+ await WebDownloadStringAsync(website);
+
+ // Log it
+ Log("After async await thread");
+
+ Console.WriteLine("---------------------------------------------");
+ });
+
+ // Wait the main task
+ task.Wait();
+
+ #endregion
+
+ // Async and await are always used together. A method or lambda tagged with
+ // async can then await any Task
+ //
+ // When you await something, the thread which called the await is free to then return to
+ // what it was doing, while in parallel the task inside the await is now run on another thread.
+ //
+ // Once the task is done, it returns either to the original calling thread, or carries on,
+ // on another thread to do the work that codes after the await.
+ //
+ //
+ //
+ // Async Analogy
+ // ===============
+ //
+ // Imagine you go to Starbucks and the entire shop is run by one person.
+ // His name is Mr UI Thread. You walk in and ask Mr Thread for a Vanilla Latte.
+ // He obliges and starts to make your coffee.
+ //
+ // He puts the milk into the container and turns on the hot steam, and proceeds
+ // to stand there and wait for the milk to reach 70 degrees.
+ //
+ // During this time you remember you wanted a muffin as well, so you shout over
+ // to Mr Thread and ask for a muffin... but he ignores you. He is blocked
+ // waiting for the milk to boil.
+ //
+ // Several minutes goes by and 3 more customers have come in and are waiting
+ // to be served. Finally the milk is finished and he completes the Latte.
+ // Returning to you. You are a little annoyed at being ignored for minutes
+ // and decide to leave your muffin.
+ //
+ // Then he continues to serve one customer at a time, doing one job at a time.
+ // Not a good situation.
+ //
+ // This is what happens with a single threaded application.
+ //
+ // Now in order to improve business Mr Thread employs 2 new members of staff
+ // called Mrs and Mrs Worker Thread. The pair work well independently and
+ // as Mr Thread takes orders from the customers, he asks Mrs Worker Thread
+ // to complete the order, and then without waiting for Mrs Worker Thread to
+ // finish the drink, proceeds to serve the next customer.
+ //
+ // Once Mrs Worker Thread has finished a drink, instead of having to take
+ // the drinks to the customers she asks Mr Worker Thread to serve the drinks
+ // and then without waiting she proceeds to start the next order.
+ //
+ // The business is now a well-oiled, multi-threaded business.
+ //
+
+ //
+ // The Synchronous part in Tasks
+ // ===============================
+ //
+ //
+
+ #region The Synchronous Part of Tasks
+
+ // Run some work to show the synchronous parts of the call
+ Task.Run(async () =>
+ {
+ // Log it
+ Log($"Before DoWork thread");
+
+ // Do work
+ // This will return a Task and run the lines of code inside the method
+ // up until the point at which the first await is hit
+ var doWorkTask = DoWorkAsync("me");
+
+ // Await the task
+ // This will then spin off to a new thread and come with the result
+ await doWorkTask;
+
+ // Log it
+ Log($"After DoWork thread");
+
+ }).Wait();
+
+ Console.WriteLine("---------------------------------------------");
+
+ #endregion
+
+ //
+ // Async Return Types
+ // ====================
+ //
+ // You can only return void, Task or Task for a method marked as async, as the method is
+ // not complete when it returns, so no other result is valid.
+ //
+
+ #region Method 1 Getting Result of Async From Sync
+
+ // Get the task
+ var doWorkResultTask = DoWorkAndGetResultAsync("Return this");
+
+ // Wait for it
+ doWorkResultTask.Wait();
+
+ // Get the result
+ var doWorkResult = doWorkResultTask.Result;
+
+ Console.WriteLine("---------------------------------------------");
+
+ #endregion
+
+ #region Method 2 Getting Result of Async From Sync
+
+ Task.Run(async () =>
+ {
+ var doWorkResult2 = await DoWorkAndGetResultAsync("Return this 2");
+
+ }).Wait();
+
+ Console.WriteLine("---------------------------------------------");
+
+ #endregion
+
+ //
+ // Async Keyword
+ // ===============
+ //
+ // The async keyword is not actually added to the method declaration signature,
+ // the only effect is has is to change the compiled code.
+ //
+ // That's why interfaces cannot declare async, as it isn't a declarative statement,
+ // its a compilation statement to change the flow of the function.
+ //
+
+ //
+ // Consuming Async Methods
+ // =========================
+ //
+ // The best way to consume or call a method that returns a task is to be async yourself
+ // in the caller method, to ultimately awaiting it.
+ //
+ // By that definition async methods are naturally contagious.
+ //
+
+ #region Consuming Wait
+
+ // Store the taks
+ var workResultTask = DoWorkAndGetResultAsync("Consume Wait");
+
+ // Wait for it
+ workResultTask.Wait();
+
+ // Get the result
+ var workResult = workResultTask.Result;
+
+ Console.WriteLine("---------------------------------------------");
+
+ #endregion
+
+ #region Consuming via Task
+
+ // Declare the result
+ var workResultViaTask = default(string);
+
+ // Store the taks
+ Task.Run(async () =>
+ {
+ // Get result
+ workResultViaTask = await DoWorkAndGetResultAsync("Consume via Task");
+
+ }).Wait();
+
+ Console.WriteLine("---------------------------------------------");
+
+ #endregion
+
+ //
+ // What happens during an Async call
+ // ===================================
+ //
+ // Code inside a function that returns a Task runs its code on the callers thread
+ // up until the first line that calls await. At this point in time:
+ //
+ // 1. The current thread executing your code is released (making your code asynchronous).
+ // This means from a normal point of view, your function has returned at this point
+ // (it has return the Task object).
+ //
+ // 2. Once the task you have awaited completes, your method should appear to continue
+ // from where it left off, as if it never returned from the method, so resume on
+ // the line below the await.
+ //
+ // To achieve this, C# at the point of reaching the await call:
+ //
+ // 1. Stores all local variables in the scope of the method
+ // 2. Stores the parameters of your method
+ // 3. The "this" variable to store all class-level variables
+ // 4. Stores all contexts(Execution, Security, Call)
+ //
+ // And on resuming to the line after the await, restores all of these values as if nothing
+ // had changed. All of this information is stored on the garbage collection heap.
+ //
+
+ //
+ // What is happening with threads during an async call
+ // =====================================================
+ //
+ // As you call a method that returns a `Task` and uses `async`, inside the method all code,
+ // up until the first `await` statement, is run like a normal function on the thread that
+ // called it.
+ //
+ // Once it hits the `await` the function returns the `Task` to the caller, and does its work
+ // thats inside the `await` call on a new thread (or existing).
+ //
+ // Once its done, and effectively "after" the `await` line, execution returns to a certain
+ // thread.
+ //
+ // That thread is determined by first checking if the thread has an synchronization context
+ // and if it does it asks that what thread to return to. For UI threads this will return work
+ // to the UI thread itself.
+ //
+
+ // Console application has no synchronization context
+ var syncContext = SynchronizationContext.Current;
+
+ //
+ // For normal threads that have no synchronization context, the code after the `await`
+ // typically, but not always, continues on the same thread that the inner work was being done
+ // on, but has no requirement to resume on any specific thread.
+ //
+ // Typically if you use `ContinueWith` instead of `await`, the code inside `ContinueWith` runs
+ // on a different thread than the inner task was running on, and using `await` typically
+ // continues on the same thread.
+ //
+
+ // Show ContinueWith typically changing thread ID's
+ DoWorkAsync("ContinueWith").ContinueWith(t =>
+ {
+ Log("ContinueWith Complete");
+ }).Wait();
+
+ Console.WriteLine("---------------------------------------------");
+
+ //
+ // This also means after every await the next line is typically on a new thread if there is no
+ // synchronization context.
+ //
+ // **********************************************************************************************
+ //
+ // An exception is if you use `ConfigureAwait(false)` then the SynchronizationContext is
+ // totally ignored and the resuming thread is treated as if there were no context.
+ //
+ // Resuming on the original thread via the synchronization context is an expensive thing
+ // (takes time) and so if you choose to not care about resuming on the same thread and want
+ // to save time you can use `ConfigureAwait` to remove that overhead
+ //
+ // **********************************************************************************************
+ //
+
+ //
+ // Exceptions in Async calls
+ // ===========================
+ //
+ // Any exceptions thrown that are not caught by the method itself are thrown into the Task
+ // objects value `IsFaulted` and the `Exception` property.
+ //
+ // If you do not await the Task, the exception will not throw on your calling thread.
+ //
+
+ #region Throw on Calling Thread, Without Awaiting
+
+ Log("Before ThrowAwait");
+
+ var crashedTask = ThrowAwait(true);
+
+ // Did it crash?
+ var isFaulted = crashedTask.IsFaulted;
+
+ // The exception
+ Log(crashedTask.Exception.Message);
+
+ Log("After ThrowAwait");
+
+ #endregion
+
+ //
+ // If you await, the exception will rethrow onto the caller thread that awaited it.
+ //
+ // The exception to the rule is a method with async void. As it cannot be awaited, any
+ // exceptions that occur in an async void method are re-thrown like this:
+ //
+ // 1. If there is a synchronization context the exception is Post back to the caller thread.
+ // 2. If not, it is thrown on the thread pool
+ //
+
+ #region Throw on Calling Thread, Without Awaiting
+
+ Log("Before ThrowVoid");
+
+ ThrowAwaitVoid(true);
+
+ Log("After ThrowVoid");
+
+ #endregion
+
+ Console.ReadLine();
+ }
+
+ #region Helper Methods
+
+ ///
+ /// Output a message with the current thread ID appended
+ ///
+ ///
+ private static void Log(string message)
+ {
+ // Write line
+ Console.WriteLine($"{message} [{Thread.CurrentThread.ManagedThreadId}]");
+ }
+
+ #endregion
+
+ #region Thread Methods
+
+ ///
+ /// Shows an event-based thread callback via a method
+ ///
+ /// The callback to call once the work is complete
+ private static void EventThreadCallbackMethod(Action completed)
+ {
+ // Start a new thread
+ new Thread(() =>
+ {
+ // Log it
+ Log("Inside event thread method");
+
+ // Sleep
+ Thread.Sleep(500);
+
+ // Fire completed event
+ completed();
+
+ }).Start();
+ }
+
+ #endregion
+
+ #region Task Example Methods
+
+ ///
+ /// Downloads a string from a website URL sychronously
+ ///
+ /// The URL to download
+ private static void WebDownloadString(string url)
+ {
+ // Synchronous pattern
+ var webClient = new WebClient();
+ var result = webClient.DownloadString(url);
+
+ // Log
+ Log($"Downloaded {url}. {result.Substring(0, 10)}");
+ }
+
+ ///
+ /// Downloads a string from a website URL asychronously
+ ///
+ /// The URL to download
+ private static async Task WebDownloadStringAsync(string url)
+ {
+ // Asynchronous pattern
+ var webClient = new WebClient();
+ var result = await webClient.DownloadStringTaskAsync(new Uri(url));
+
+ // Log
+ Log($"Downloaded {url}. {result.Substring(0, 10)}");
+ }
+
+ ///
+ /// Does some work asynchronously for somebody
+ ///
+ /// Who we are doing the work for
+ ///
+ private static async Task DoWorkAsync(string forWho)
+ {
+ // Log it
+ Log($"Doing work for {forWho}");
+
+ // Start a new task (so it runs on a different thread)
+ await Task.Run(async () =>
+ {
+ // Log it
+ Log($"Doing work on inner thread for {forWho}");
+
+ // Wait
+ await Task.Delay(500);
+
+ // Log it
+ Log($"Done work on inner thread for {forWho}");
+ });
+
+ // Log it
+ Log($"Done work for {forWho}");
+ }
+
+ ///
+ /// Does some work asynchronously for somebody, and return a result
+ ///
+ /// Who we are doing the work for
+ ///
+ private static async Task DoWorkAndGetResultAsync(string forWho)
+ {
+ // Log it
+ Log($"Doing work for {forWho}");
+
+ // Start a new task (so it runs on a different thread)
+ await Task.Run(async () =>
+ {
+ // Log it
+ Log($"Doing work on inner thread for {forWho}");
+
+ // Wait
+ await Task.Delay(500);
+
+ // Log it
+ Log($"Done work on inner thread for {forWho}");
+ });
+
+ // Log it
+ Log($"Done work for {forWho}");
+
+ // Return what we received
+ return forWho;
+ }
+
+ ///
+ /// Throws an exception inside a task
+ ///
+ /// Throws the exception before an await
+ ///
+ private static async Task ThrowAwait(bool before)
+ {
+ if (before)
+ throw new ArgumentException("Oopps");
+
+ await Task.Delay(1);
+
+ throw new ArgumentException("Oopps");
+ }
+
+ ///
+ /// Throws an exception inside a void async before awaiting
+ ///
+ /// Throws the exception before an await
+ ///
+ private static async void ThrowAwaitVoid(bool before)
+ {
+ if (before)
+ throw new ArgumentException("Oopps");
+
+ await Task.Delay(1);
+
+ throw new ArgumentException("Oopps");
+ }
+ #endregion
+ }
+}
diff --git a/Tasks/TasksInConsole/TasksInConsole/TasksInConsole.csproj b/Tasks/TasksInConsole/TasksInConsole/TasksInConsole.csproj
new file mode 100644
index 0000000..ce1697a
--- /dev/null
+++ b/Tasks/TasksInConsole/TasksInConsole/TasksInConsole.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
diff --git a/Tasks/TasksInWPF/TasksInWPF.sln b/Tasks/TasksInWPF/TasksInWPF.sln
new file mode 100644
index 0000000..3b89199
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.2037
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TasksInWPF", "TasksInWPF\TasksInWPF.csproj", "{A88A9774-8313-4863-9C8C-3D1121FC952C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A88A9774-8313-4863-9C8C-3D1121FC952C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A88A9774-8313-4863-9C8C-3D1121FC952C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A88A9774-8313-4863-9C8C-3D1121FC952C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A88A9774-8313-4863-9C8C-3D1121FC952C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4C1A1660-0727-4C09-B893-481DCA678748}
+ EndGlobalSection
+EndGlobal
diff --git a/Tasks/TasksInWPF/TasksInWPF/App.config b/Tasks/TasksInWPF/TasksInWPF/App.config
new file mode 100644
index 0000000..731f6de
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tasks/TasksInWPF/TasksInWPF/App.xaml b/Tasks/TasksInWPF/TasksInWPF/App.xaml
new file mode 100644
index 0000000..d7e6c92
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Tasks/TasksInWPF/TasksInWPF/App.xaml.cs b/Tasks/TasksInWPF/TasksInWPF/App.xaml.cs
new file mode 100644
index 0000000..788d26f
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace TasksInWPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml b/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml
new file mode 100644
index 0000000..9feb283
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml.cs b/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml.cs
new file mode 100644
index 0000000..aea769b
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/MainWindow.xaml.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace TasksInWPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ #region Private Members
+
+ ///
+ /// Whether to do synchronous work on UI thread or not
+ ///
+ private bool mDoSynchronousWork = false;
+
+ #endregion
+
+ #region Constructor
+
+ ///
+ /// Default constructor
+ ///
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ #endregion
+
+ private async void Button_Click(object sender, RoutedEventArgs e)
+ {
+ #region Doing synchronous work on UI thread
+
+ if (mDoSynchronousWork)
+ {
+ Log("Start synchronous work");
+
+ Thread.Sleep(5000);
+
+ Log("End synchronous work");
+ }
+
+ #endregion
+
+ #region Doing Async work on UI thread
+
+ // Log it
+ Log("Start asynchronous work");
+
+ // Remember UI context
+ // var uiSyncContext = SynchronizationContext.Current;
+
+ // To kill UI sync context on capture in await
+ // SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
+
+ // Run some async work
+ await DoWorkAsync("Async"); //.ConfigureAwait(false);
+
+ // Should resume on same UI thread, thanks to SynchronizationContext
+
+ // Set UI stuff
+ // uiSyncContext.Post((s) =>
+ // {
+ // MyButton.Content = "New content";
+ // }, null);
+
+ // MyButton.Content = "New content";
+
+ // Log it
+ Log("End asynchronous work");
+
+ #endregion
+ }
+
+ #region Helper Methods
+
+ ///
+ /// Output a message with the current thread ID appended
+ ///
+ ///
+ private static void Log(string message)
+ {
+ // Write line
+ Debug.WriteLine($"{message} [{Thread.CurrentThread.ManagedThreadId}]");
+ }
+
+ #endregion
+
+
+ ///
+ /// Does some work asynchronously for somebody
+ ///
+ /// Who we are doing the work for
+ ///
+ private static async Task DoWorkAsync(string forWho)
+ {
+ // Log it
+ Log($"Doing work for {forWho}");
+
+ // Start a new task (so it runs on a different thread)
+ await Task.Run(async () =>
+ {
+ // Log it
+ Log($"Doing work on inner thread for {forWho}");
+
+ // Wait
+ await Task.Delay(500);
+
+ // Log it
+ Log($"Done work on inner thread for {forWho}");
+ });
+
+ // Log it
+ Log($"Done work for {forWho}");
+ }
+
+ }
+}
diff --git a/Tasks/TasksInWPF/TasksInWPF/Properties/AssemblyInfo.cs b/Tasks/TasksInWPF/TasksInWPF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0f56467
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TasksInWPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TasksInWPF")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.Designer.cs b/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..5fe5a89
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TasksInWPF.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TasksInWPF.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.resx b/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.Designer.cs b/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..c63335a
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TasksInWPF.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.settings b/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tasks/TasksInWPF/TasksInWPF/TasksInWPF.csproj b/Tasks/TasksInWPF/TasksInWPF/TasksInWPF.csproj
new file mode 100644
index 0000000..e4fd591
--- /dev/null
+++ b/Tasks/TasksInWPF/TasksInWPF/TasksInWPF.csproj
@@ -0,0 +1,97 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A88A9774-8313-4863-9C8C-3D1121FC952C}
+ WinExe
+ TasksInWPF
+ TasksInWPF
+ v4.6.1
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
\ No newline at end of file