Tasks example

This commit is contained in:
Luke Malpass
2018-04-13 12:09:45 +01:00
parent 5be2c290ca
commit 67ad430308
15 changed files with 1369 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,767 @@
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace TasksInConsole
{
class Program
{
#region Private Members
/// <summary>
/// The event finished callback for the Thread event example
/// </summary>
private static event Action EventFinished = () => { };
/// <summary>
/// Whether to run the thread examples
/// </summary>
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<T> 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
/// <summary>
/// Output a message with the current thread ID appended
/// </summary>
/// <param name="message"></param>
private static void Log(string message)
{
// Write line
Console.WriteLine($"{message} [{Thread.CurrentThread.ManagedThreadId}]");
}
#endregion
#region Thread Methods
/// <summary>
/// Shows an event-based thread callback via a method
/// </summary>
/// <param name="completed">The callback to call once the work is complete</param>
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
/// <summary>
/// Downloads a string from a website URL sychronously
/// </summary>
/// <param name="url">The URL to download</param>
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)}");
}
/// <summary>
/// Downloads a string from a website URL asychronously
/// </summary>
/// <param name="url">The URL to download</param>
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)}");
}
/// <summary>
/// Does some work asynchronously for somebody
/// </summary>
/// <param name="forWho">Who we are doing the work for</param>
/// <returns></returns>
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}");
}
/// <summary>
/// Does some work asynchronously for somebody, and return a result
/// </summary>
/// <param name="forWho">Who we are doing the work for</param>
/// <returns></returns>
private static async Task<string> 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;
}
/// <summary>
/// Throws an exception inside a task
/// </summary>
/// <param name="before">Throws the exception before an await</param>
/// <returns></returns>
private static async Task ThrowAwait(bool before)
{
if (before)
throw new ArgumentException("Oopps");
await Task.Delay(1);
throw new ArgumentException("Oopps");
}
/// <summary>
/// Throws an exception inside a void async before awaiting
/// </summary>
/// <param name="before">Throws the exception before an await</param>
/// <returns></returns>
private static async void ThrowAwaitVoid(bool before)
{
if (before)
throw new ArgumentException("Oopps");
await Task.Delay(1);
throw new ArgumentException("Oopps");
}
#endregion
}
}

View File

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@ -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

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

View File

@ -0,0 +1,9 @@
<Application x:Class="TasksInWPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TasksInWPF"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -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
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -0,0 +1,12 @@
<Window x:Class="TasksInWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TasksInWPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Button x:Name="MyButton" Content="Click me" Click="Button_Click" />
</StackPanel>
</Window>

View File

@ -0,0 +1,123 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace TasksInWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Private Members
/// <summary>
/// Whether to do synchronous work on UI thread or not
/// </summary>
private bool mDoSynchronousWork = false;
#endregion
#region Constructor
/// <summary>
/// Default constructor
/// </summary>
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
/// <summary>
/// Output a message with the current thread ID appended
/// </summary>
/// <param name="message"></param>
private static void Log(string message)
{
// Write line
Debug.WriteLine($"{message} [{Thread.CurrentThread.ManagedThreadId}]");
}
#endregion
/// <summary>
/// Does some work asynchronously for somebody
/// </summary>
/// <param name="forWho">Who we are doing the work for</param>
/// <returns></returns>
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}");
}
}
}

View File

@ -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
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> 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")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TasksInWPF.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A88A9774-8313-4863-9C8C-3D1121FC952C}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>TasksInWPF</RootNamespace>
<AssemblyName>TasksInWPF</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>