Skip to content

Commit 81eddfb

Browse files
committed
Initial checkin
0 parents  commit 81eddfb

File tree

55 files changed

+1411
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1411
-0
lines changed

.vs/AsyncTesting/v15/.suo

39.5 KB
Binary file not shown.
668 KB
Binary file not shown.

AsyncTesting.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.26730.10
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFGui", "AsyncTesting\WPFGui.csproj", "{201924C3-E71B-4F00-9F77-9024E7D90DF9}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{201924C3-E71B-4F00-9F77-9024E7D90DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{201924C3-E71B-4F00-9F77-9024E7D90DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{201924C3-E71B-4F00-9F77-9024E7D90DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{201924C3-E71B-4F00-9F77-9024E7D90DF9}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {DA20A861-E8E5-4D41-B6BB-1E15515C6F31}
24+
EndGlobalSection
25+
EndGlobal

AsyncTesting/App.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
5+
</startup>
6+
</configuration>

AsyncTesting/App.xaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Application x:Class="AsyncTesting.App"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:local="clr-namespace:AsyncTesting"
5+
StartupUri="MainWindow.xaml">
6+
<Application.Resources>
7+
<Style TargetType="Label">
8+
<Setter Property="Padding" Value="3" />
9+
<Setter Property="Margin" Value="3" />
10+
<Setter Property="FontSize" Value="14" />
11+
<Setter Property="FontWeight" Value="Bold"/>
12+
</Style>
13+
14+
<Style TargetType="TextBox">
15+
<Setter Property="Padding" Value="3" />
16+
<Setter Property="Margin" Value="3" />
17+
<Setter Property="FontSize" Value="14" />
18+
<Setter Property="HorizontalAlignment" Value="Stretch" />
19+
</Style>
20+
21+
<Style TargetType="Button" >
22+
<Setter Property="HorizontalAlignment" Value="Left" />
23+
<Setter Property="Width" Value="250" />
24+
<Setter Property="Margin" Value="5" />
25+
</Style>
26+
27+
</Application.Resources>
28+
</Application>

AsyncTesting/App.xaml.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Configuration;
4+
using System.Data;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
using System.Windows;
8+
9+
namespace AsyncTesting
10+
{
11+
/// <summary>
12+
/// Interaction logic for App.xaml
13+
/// </summary>
14+
public partial class App : Application
15+
{
16+
}
17+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using AsyncTesting.Models;
2+
using System;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using System.Windows.Input;
6+
7+
namespace AsyncTesting.Commands
8+
{
9+
public class SaveAndDeadLock : ICommand
10+
{
11+
public event EventHandler CanExecuteChanged;
12+
13+
public bool CanExecute(object parameter)
14+
{
15+
return true;
16+
}
17+
18+
/// <summary>
19+
/// Deadlocks
20+
/// </summary>
21+
/// <param name="parameter"></param>
22+
public void Execute(object parameter)
23+
{
24+
TheViewModel vm = parameter as TheViewModel;
25+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
26+
27+
//Blocks while CallSomethingAsync runs. CallSomethingAsync
28+
//cannot resume on the context because .Result is blocking.
29+
string msg = CallSomethingAsync(vm).Result;
30+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
31+
vm.UpdateDescription(msg);
32+
}
33+
34+
private async Task<string> CallSomethingAsync(TheViewModel vm)
35+
{
36+
await Task.Delay(10);
37+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
38+
await Task.Delay(1000);
39+
return $"You will never see this message.";
40+
}
41+
}
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using AsyncTesting.Models;
2+
using System;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using System.Windows.Input;
6+
7+
namespace AsyncTesting.Commands
8+
{
9+
public class SaveAndDeadLockEvenWithConfigureAwaitFalse : ICommand
10+
{
11+
public event EventHandler CanExecuteChanged;
12+
13+
public bool CanExecute(object parameter)
14+
{
15+
return true;
16+
}
17+
18+
/// <summary>
19+
/// Deadlocks
20+
/// </summary>
21+
/// <param name="parameter"></param>
22+
public void Execute(object parameter)
23+
{
24+
TheViewModel vm = parameter as TheViewModel;
25+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
26+
27+
//Blocks while CallSomethingAsync runs. CallSomethingAsync
28+
//has switched contexts even though ConfigureAwait(false)
29+
//is used! This is because the library code does not also
30+
//use ConfigureAwait(false);
31+
string msg = CallSomethingAsync(vm).Result;
32+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
33+
vm.UpdateDescription(msg);
34+
}
35+
36+
private async Task<string> CallSomethingAsync(TheViewModel vm)
37+
{
38+
LibraryCode lc = new LibraryCode();
39+
string msg = await lc.BadEttiquette().ConfigureAwait(continueOnCapturedContext:false);
40+
return msg;
41+
}
42+
}
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using AsyncTesting.Models;
2+
using System;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using System.Windows.Input;
6+
7+
namespace AsyncTesting.Commands
8+
{
9+
public class SaveContextAware : ICommand
10+
{
11+
public event EventHandler CanExecuteChanged;
12+
13+
public bool CanExecute(object parameter)
14+
{
15+
return true;
16+
}
17+
18+
/// <summary>
19+
/// Works because we never switch contexts
20+
/// </summary>
21+
/// <param name="parameter"></param>
22+
public async void Execute(object parameter)
23+
{
24+
TheViewModel vm = parameter as TheViewModel;
25+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
26+
27+
//Remains context aware
28+
string msg = await CallSomethingAsync(vm);
29+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
30+
vm.UpdateDescription(msg);
31+
}
32+
33+
private async Task<string> CallSomethingAsync(TheViewModel vm)
34+
{
35+
await Task.Delay(10);
36+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
37+
await Task.Delay(1000);
38+
return $"Never switched contexts.";
39+
}
40+
}
41+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using AsyncTesting.Models;
2+
using System;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using System.Windows.Input;
6+
7+
namespace AsyncTesting.Commands
8+
{
9+
public class SaveCrossContext : ICommand
10+
{
11+
public event EventHandler CanExecuteChanged;
12+
13+
public bool CanExecute(object parameter)
14+
{
15+
return true;
16+
}
17+
18+
/// <summary>
19+
/// Blows up because trying to access GUI from wrong context.
20+
/// </summary>
21+
/// <param name="parameter"></param>
22+
public async void Execute(object parameter)
23+
{
24+
TheViewModel vm = parameter as TheViewModel;
25+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
26+
27+
//Switching to default context here.
28+
string msg = await CallSomethingAsync(vm).ConfigureAwait(continueOnCapturedContext: false);
29+
30+
//Still on default context, no access to GUI thread. Boom.
31+
vm.UpdateDescription(msg);
32+
}
33+
34+
private async Task<string> CallSomethingAsync(TheViewModel vm)
35+
{
36+
await Task.Delay(10).ConfigureAwait(continueOnCapturedContext:false);
37+
vm.CurrentThreadID = Thread.CurrentThread.ManagedThreadId;
38+
await Task.Delay(1000);
39+
return "You will never see this message";
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)