Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@@ -0,0 +1,101 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Tests", "tests\System.Threading.Tasks.Tests.csproj", "{B6C09633-D161-499A-8FE1-46B2D53A16E7}"
ProjectSection(ProjectDependencies) = postProject
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA} = {3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks", "src\System.Threading.Tasks.csproj", "{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU = DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU
ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU = ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU
DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU = DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU
ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU = ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU
DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU = DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU
ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU = ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU
DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU = DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU
ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU = ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU
DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU = DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU
ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU = ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU
DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU = DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU
ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU = ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU
DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU = DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU
ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU = ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU
DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU = DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU
ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU = ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{B6C09633-D161-499A-8FE1-46B2D53A16E7}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = uap101aot-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = uap101aot-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = uap101aot-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = uap101aot-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = uap101aot-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = uap101aot-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = uap101aot-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppuap101aot-Windows_NTnetcoreapp|AnyCPU.Build.0 = uap101aot-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = net463-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = net463-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = net463-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = net463-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = net463-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = net463-Windows_NT-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.ActiveCfg = net463-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnet463-Windows_NTnetcoreapp|AnyCPU.Build.0 = net463-Windows_NT-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp1.2corert-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp1.2corert-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp1.2corert-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp1.2corert-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp1.2corert-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.DebugNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp1.2corert-Debug|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.ActiveCfg = netcoreapp1.2corert-Release|Any CPU
{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}.ReleaseNETCoreAppnetcoreapp1.2corertnetcoreapp|AnyCPU.Build.0 = netcoreapp1.2corert-Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.1.0.0</AssemblyVersion>
<IsNETCoreApp>true</IsNETCoreApp>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netcoreapp;
uap;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,157 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ------------------------------------------------------------------------------
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------
// These types were moved down to System.Runtime
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.AggregateException))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.ICriticalNotifyCompletion))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.INotifyCompletion))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.TaskAwaiter))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.TaskAwaiter<>))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.YieldAwaitable))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.CancellationToken))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.CancellationTokenRegistration))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Task))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.Task<>))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskContinuationOptions))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskCreationOptions))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskFactory))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskFactory<>))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskScheduler))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.TaskStatus))]
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Threading.Tasks.UnobservedTaskExceptionEventArgs))]
namespace System
{
public partial class OperationCanceledException : System.SystemException
{
public OperationCanceledException() { }
public OperationCanceledException(string message) { }
public OperationCanceledException(string message, System.Exception innerException) { }
public OperationCanceledException(string message, System.Exception innerException, System.Threading.CancellationToken token) { }
public OperationCanceledException(string message, System.Threading.CancellationToken token) { }
public OperationCanceledException(System.Threading.CancellationToken token) { }
protected OperationCanceledException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } }
}
}
namespace System.Runtime.CompilerServices
{
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct AsyncTaskMethodBuilder
{
public System.Threading.Tasks.Task Task { get { throw null; } }
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public static System.Runtime.CompilerServices.AsyncTaskMethodBuilder Create() { throw null; }
public void SetException(System.Exception exception) { }
public void SetResult() { }
public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct AsyncTaskMethodBuilder<TResult>
{
public System.Threading.Tasks.Task<TResult> Task { get { throw null; } }
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public static System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult> Create() { throw null; }
public void SetException(System.Exception exception) { }
public void SetResult(TResult result) { }
public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct AsyncVoidMethodBuilder
{
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
public static System.Runtime.CompilerServices.AsyncVoidMethodBuilder Create() { throw null; }
public void SetException(System.Exception exception) { }
public void SetResult() { }
public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
}
public partial interface IAsyncStateMachine
{
void MoveNext();
void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine);
}
}
namespace System.Threading
{
public partial class CancellationTokenSource : System.IDisposable
{
public CancellationTokenSource() { }
public CancellationTokenSource(int millisecondsDelay) { }
public CancellationTokenSource(System.TimeSpan delay) { }
public bool IsCancellationRequested { get { throw null; } }
public System.Threading.CancellationToken Token { get { throw null; } }
public void Cancel() { }
public void Cancel(bool throwOnFirstException) { }
public void CancelAfter(int millisecondsDelay) { }
public void CancelAfter(System.TimeSpan delay) { }
public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token1, System.Threading.CancellationToken token2) { throw null; }
public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(params System.Threading.CancellationToken[] tokens) { throw null; }
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
}
}
namespace System.Threading.Tasks
{
public partial class ConcurrentExclusiveSchedulerPair
{
public ConcurrentExclusiveSchedulerPair() { }
public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler) { }
public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler, int maxConcurrencyLevel) { }
public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask) { }
public System.Threading.Tasks.Task Completion { get { throw null; } }
public System.Threading.Tasks.TaskScheduler ConcurrentScheduler { get { throw null; } }
public System.Threading.Tasks.TaskScheduler ExclusiveScheduler { get { throw null; } }
public void Complete() { }
}
public partial class TaskCanceledException : System.OperationCanceledException
{
public TaskCanceledException() { }
public TaskCanceledException(string message) { }
public TaskCanceledException(string message, System.Exception innerException) { }
public TaskCanceledException(System.Threading.Tasks.Task task) { }
protected TaskCanceledException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public System.Threading.Tasks.Task Task { get { throw null; } }
}
public partial class TaskCompletionSource<TResult>
{
public TaskCompletionSource() { }
public TaskCompletionSource(object state) { }
public TaskCompletionSource(object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
public TaskCompletionSource(System.Threading.Tasks.TaskCreationOptions creationOptions) { }
public System.Threading.Tasks.Task<TResult> Task { get { throw null; } }
public void SetCanceled() { }
public void SetException(System.Collections.Generic.IEnumerable<System.Exception> exceptions) { }
public void SetException(System.Exception exception) { }
public void SetResult(TResult result) { }
public bool TrySetCanceled() { throw null; }
public bool TrySetCanceled(System.Threading.CancellationToken cancellationToken) { throw null; }
public bool TrySetException(System.Collections.Generic.IEnumerable<System.Exception> exceptions) { throw null; }
public bool TrySetException(System.Exception exception) { throw null; }
public bool TrySetResult(TResult result) { throw null; }
}
public static partial class TaskExtensions
{
public static System.Threading.Tasks.Task Unwrap(this System.Threading.Tasks.Task<System.Threading.Tasks.Task> task) { throw null; }
public static System.Threading.Tasks.Task<TResult> Unwrap<TResult>(this System.Threading.Tasks.Task<System.Threading.Tasks.Task<TResult>> task) { throw null; }
}
public partial class TaskSchedulerException : System.Exception
{
public TaskSchedulerException() { }
public TaskSchedulerException(System.Exception innerException) { }
public TaskSchedulerException(string message) { }
public TaskSchedulerException(string message, System.Exception innerException) { }
protected TaskSchedulerException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
}
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System.Threading.Tasks.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -0,0 +1,11 @@
Compat issues with assembly System.Threading.Tasks:
CannotRemoveBaseTypeOrInterface : Type 'System.OperationCanceledException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.OperationCanceledException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose(System.Boolean)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task<TResult>' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.TaskCanceledException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Tasks.TaskCanceledException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Tasks.TaskSchedulerException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
Total Issues: 9

View File

@@ -0,0 +1,12 @@
Compat issues with assembly System.Threading.Tasks:
MembersMustExist : Member 'System.AggregateException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.OperationCanceledException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.OperationCanceledException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Tasks.Task.Dispose(System.Boolean)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.Task<TResult>' does not implement interface 'System.IDisposable' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'System.Threading.Tasks.TaskCanceledException' does not inherit from base type 'System.SystemException' in the implementation but it does in the contract.
MembersMustExist : Member 'System.Threading.Tasks.TaskCanceledException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'System.Threading.Tasks.TaskSchedulerException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' does not exist in the implementation but it does exist in the contract.
Total Issues: 10

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
uap101aot-Windows_NT;
net463-Windows_NT;
netcoreapp-Windows_NT;
netcoreapp-Unix;
netcoreapp1.2corert;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{3BCAEAA6-3A29-49EC-B334-6E7BE8BE9ABA}</ProjectGuid>
<AssemblyName>System.Threading.Tasks</AssemblyName>
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp1.2corert-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp1.2corert-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap101aot-Windows_NT-Release|AnyCPU'" />
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
<Compile Include="System\Threading\Tasks\TaskExtensions.CoreCLR.cs" />
<ProjectReference Include="..\..\System.Diagnostics.Debug\src\System.Diagnostics.Debug.csproj" />
<TargetingPackReference Include="System.Private.CoreLib" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'net463'">
<TargetingPackReference Include="mscorlib" />
<TargetingPackReference Include="System.Core" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'uap101aot' or '$(TargetGroup)' == 'netcoreapp1.2corert'">
<Compile Include="System\Threading\Tasks\TaskExtensions.CoreRT.cs" />
<TargetingPackReference Include="System.Private.CoreLib" />
</ItemGroup>
<ItemGroup>
<ReferenceFromRuntime Include="System.Private.CoreLib" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -0,0 +1,229 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
/// <summary>
/// Provides a set of static (Shared in Visual Basic) methods for working with specific kinds of
/// <see cref="System.Threading.Tasks.Task"/> instances.
/// </summary>
public static class TaskExtensions
{
/// <summary>
/// Creates a proxy <see cref="System.Threading.Tasks.Task">Task</see> that represents the
/// asynchronous operation of a Task{Task}.
/// </summary>
/// <remarks>
/// It is often useful to be able to return a Task from a <see cref="System.Threading.Tasks.Task{TResult}">
/// Task{TResult}</see>, where the inner Task represents work done as part of the outer Task{TResult}. However,
/// doing so results in a Task{Task}, which, if not dealt with carefully, could produce unexpected behavior. Unwrap
/// solves this problem by creating a proxy Task that represents the entire asynchronous operation of such a Task{Task}.
/// </remarks>
/// <param name="task">The Task{Task} to unwrap.</param>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown if the
/// <paramref name="task"/> argument is null.</exception>
/// <returns>A Task that represents the asynchronous operation of the provided Task{Task}.</returns>
public static Task Unwrap(this Task<Task> task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
// Fast path for an already successfully completed outer task: just return the inner one.
// As in the subsequent slower path, a null inner task is special-cased to mean cancellation.
if (task.Status == TaskStatus.RanToCompletion && (task.CreationOptions & TaskCreationOptions.AttachedToParent) == 0)
{
return task.Result ?? Task.FromCanceled(new CancellationToken(true));
}
// Create a new Task to serve as a proxy for the actual inner task. Attach it
// to the parent if the original was attached to the parent.
var tcs = new TaskCompletionSource<VoidResult>(task.CreationOptions & TaskCreationOptions.AttachedToParent);
TransferAsynchronously(tcs, task);
return tcs.Task;
}
/// <summary>
/// Creates a proxy <see cref="System.Threading.Tasks.Task{TResult}">Task{TResult}</see> that represents the
/// asynchronous operation of a Task{Task{TResult}}.
/// </summary>
/// <remarks>
/// It is often useful to be able to return a Task{TResult} from a Task{TResult}, where the inner Task{TResult}
/// represents work done as part of the outer Task{TResult}. However, doing so results in a Task{Task{TResult}},
/// which, if not dealt with carefully, could produce unexpected behavior. Unwrap solves this problem by
/// creating a proxy Task{TResult} that represents the entire asynchronous operation of such a Task{Task{TResult}}.
/// </remarks>
/// <param name="task">The Task{Task{TResult}} to unwrap.</param>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown if the
/// <paramref name="task"/> argument is null.</exception>
/// <returns>A Task{TResult} that represents the asynchronous operation of the provided Task{Task{TResult}}.</returns>
public static Task<TResult> Unwrap<TResult>(this Task<Task<TResult>> task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
// Fast path for an already successfully completed outer task: just return the inner one.
// As in the subsequent slower path, a null inner task is special-cased to mean cancellation.
if (task.Status == TaskStatus.RanToCompletion && (task.CreationOptions & TaskCreationOptions.AttachedToParent) == 0)
{
return task.Result ?? Task.FromCanceled<TResult>(new CancellationToken(true));
}
// Create a new Task to serve as a proxy for the actual inner task. Attach it
// to the parent if the original was attached to the parent.
var tcs = new TaskCompletionSource<TResult>(task.CreationOptions & TaskCreationOptions.AttachedToParent);
TransferAsynchronously(tcs, task);
return tcs.Task;
}
/// <summary>
/// Transfer the results of the <paramref name="outer"/> task's inner task to the <paramref name="completionSource"/>.
/// </summary>
/// <param name="completionSource">The completion source to which results should be transfered.</param>
/// <param name="outer">
/// The outer task that when completed will yield an inner task whose results we want marshaled to the <paramref name="completionSource"/>.
/// </param>
private static void TransferAsynchronously<TResult, TInner>(TaskCompletionSource<TResult> completionSource, Task<TInner> outer) where TInner : Task
{
Action callback = null;
// Create a continuation delegate. For performance reasons, we reuse the same delegate/closure across multiple
// continuations; by using .ConfigureAwait(false).GetAwaiter().UnsafeOnComplete(action), in most cases
// this delegate can be stored directly into the Task's continuation field, eliminating the need for additional
// allocations. Thus, this whole Unwrap operation generally results in four allocations: one for the TaskCompletionSource,
// one for the returned task, one for the delegate, and one for the closure. Since the delegate is used
// across multiple continuations, we use the callback variable as well to indicate which continuation we're in:
// if the callback is non-null, then we're processing the continuation for the outer task and use the callback
// object as the continuation off of the inner task; if the callback is null, then we're processing the
// inner task.
callback = delegate
{
Debug.Assert(outer.IsCompleted);
if (callback != null)
{
// Process the outer task's completion
// Clear out the callback field to indicate that any future invocations should
// be for processing the inner task, but store away a local copy in case we need
// to use it as the continuation off of the outer task.
Action innerCallback = callback;
callback = null;
bool result = true;
switch (outer.Status)
{
case TaskStatus.Canceled:
case TaskStatus.Faulted:
// The outer task has completed as canceled or faulted; transfer that
// status to the completion source, and we're done.
result = completionSource.TrySetFromTask(outer);
break;
case TaskStatus.RanToCompletion:
Task inner = outer.Result;
if (inner == null)
{
// The outer task completed successfully, but with a null inner task;
// cancel the completionSource, and we're done.
result = completionSource.TrySetCanceled();
}
else if (inner.IsCompleted)
{
// The inner task also completed! Transfer the results, and we're done.
result = completionSource.TrySetFromTask(inner);
}
else
{
// Run this delegate again once the inner task has completed.
inner.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(innerCallback);
}
break;
}
Debug.Assert(result);
}
else
{
// Process the inner task's completion. All we need to do is transfer its results
// to the completion source.
Debug.Assert(outer.Status == TaskStatus.RanToCompletion);
Debug.Assert(outer.Result.IsCompleted);
completionSource.TrySetFromTask(outer.Result);
}
};
// Kick things off by hooking up the callback as the task's continuation
outer.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(callback);
}
/// <summary>Copies that ending state information from <paramref name="task"/> to <paramref name="completionSource"/>.</summary>
private static bool TrySetFromTask<TResult>(this TaskCompletionSource<TResult> completionSource, Task task)
{
Debug.Assert(task.IsCompleted);
// Before transferring the results, check to make sure we're not too deep on the stack. Calling TrySet*
// will cause any synchronous continuations to be invoked, which is fine unless we're so deep that doing
// so overflows. ContinueWith has built-in support for avoiding such stack dives, but that support is not
// (yet) part of await's infrastructure, so until it is we mimic it manually. This matches the behavior
// employed by the Unwrap implementation in mscorlib.
if (!RuntimeHelpers.TryEnsureSufficientExecutionStack())
{
// This is very rare. We're too deep to safely invoke
// TrySet* synchronously, so do so asynchronously instead.
Task.Factory.StartNew(s =>
{
var t = (Tuple<TaskCompletionSource<TResult>, Task>)s;
TrySetFromTask(t.Item1, t.Item2);
}, Tuple.Create(completionSource, task), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
return true;
}
// Transfer the results from the supplied Task to the TaskCompletionSource.
bool result = false;
switch(task.Status)
{
case TaskStatus.Canceled:
result = completionSource.TrySetCanceled(ExtractCancellationToken(task));
break;
case TaskStatus.Faulted:
result = completionSource.TrySetException(task.Exception.InnerExceptions);
break;
case TaskStatus.RanToCompletion:
Task<TResult> resultTask = task as Task<TResult>;
result = resultTask != null ?
completionSource.TrySetResult(resultTask.Result) :
completionSource.TrySetResult(default(TResult));
break;
}
return result;
}
/// <summary>Gets the CancellationToken associated with a canceled task.</summary>
private static CancellationToken ExtractCancellationToken(Task task)
{
// With the public Task APIs as of .NET 4.6, the only way to extract a CancellationToken
// that was associated with a Task is by await'ing it, catching the resulting
// OperationCanceledException, and getting the token from the OCE.
Debug.Assert(task.IsCanceled);
try
{
task.GetAwaiter().GetResult();
Debug.Fail("Waiting on the canceled task should always result in an OCE, even if it's manufactured at the time of the wait.");
return new CancellationToken(true);
}
catch (OperationCanceledException oce)
{
// This token may not have cancellation requested; that's ok.
// That can happen if, for example, the Task is canceled with
// TaskCompletionSource<T>.SetCanceled(), without a token.
return oce.CancellationToken;
}
}
/// <summary>Dummy type to use as a void TResult.</summary>
private struct VoidResult { }
}
}

View File

@@ -0,0 +1,72 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace System.Threading.Tasks
{
/// <summary>
/// Provides a set of static (Shared in Visual Basic) methods for working with specific kinds of
/// <see cref="System.Threading.Tasks.Task"/> instances.
/// </summary>
public static class TaskExtensions
{
/// <summary>
/// Creates a proxy <see cref="System.Threading.Tasks.Task">Task</see> that represents the
/// asynchronous operation of a Task{Task}.
/// </summary>
/// <remarks>
/// It is often useful to be able to return a Task from a <see cref="System.Threading.Tasks.Task{TResult}">
/// Task{TResult}</see>, where the inner Task represents work done as part of the outer Task{TResult}. However,
/// doing so results in a Task{Task}, which, if not dealt with carefully, could produce unexpected behavior. Unwrap
/// solves this problem by creating a proxy Task that represents the entire asynchronous operation of such a Task{Task}.
/// </remarks>
/// <param name="task">The Task{Task} to unwrap.</param>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown if the
/// <paramref name="task"/> argument is null.</exception>
/// <returns>A Task that represents the asynchronous operation of the provided Task{Task}.</returns>
public static Task Unwrap(this Task<Task> task)
{
if (task == null)
{
throw new ArgumentNullException(nameof(task));
}
// Creates a proxy Task and hooks up the logic to have it represent the task.Result
Task promise = Task.CreateUnwrapPromise<VoidResult>(task, lookForOce: false);
// Return the proxy immediately
return promise;
}
/// <summary>
/// Creates a proxy <see cref="System.Threading.Tasks.Task{TResult}">Task{TResult}</see> that represents the
/// asynchronous operation of a Task{Task{TResult}}.
/// </summary>
/// <remarks>
/// It is often useful to be able to return a Task{TResult} from a Task{TResult}, where the inner Task{TResult}
/// represents work done as part of the outer Task{TResult}. However, doing so results in a Task{Task{TResult}},
/// which, if not dealt with carefully, could produce unexpected behavior. Unwrap solves this problem by
/// creating a proxy Task{TResult} that represents the entire asynchronous operation of such a Task{Task{TResult}}.
/// </remarks>
/// <param name="task">The Task{Task{TResult}} to unwrap.</param>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown if the
/// <paramref name="task"/> argument is null.</exception>
/// <returns>A Task{TResult} that represents the asynchronous operation of the provided Task{Task{TResult}}.</returns>
public static Task<TResult> Unwrap<TResult>(this Task<Task<TResult>> task)
{
if (task == null)
{
throw new ArgumentNullException(nameof(task));
}
// Creates a proxy Task<TResult> and hooks up the logic to have it represent the task.Result
Task<TResult> promise = Task.CreateUnwrapPromise<TResult>(task, lookForOce: false);
// Return the proxy immediately
return promise;
}
// Used as a placeholder TResult to indicate that a Task<TResult> has a void TResult
private struct VoidResult { }
}
}

View File

@@ -0,0 +1,131 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Threading.Tasks.Tests
{
public class AggregateExceptionTests
{
[Fact]
public static void ConstructorBasic()
{
AggregateException ex = new AggregateException();
Assert.Equal(ex.InnerExceptions.Count, 0);
Assert.True(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor is used, expected a default message");
ex = new AggregateException("message");
Assert.Equal(ex.InnerExceptions.Count, 0);
Assert.True(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor(string) is used");
ex = new AggregateException("message", new Exception());
Assert.Equal(ex.InnerExceptions.Count, 1);
Assert.True(ex.Message != null, "RunAggregateException_Constructor: FAILED. Message property is null when the default constructor(string, Exception) is used");
}
[Fact]
public static void ConstructorInvalidArguments()
{
AggregateException ex = new AggregateException();
Assert.Throws<ArgumentNullException>(
() => ex = new AggregateException("message", (Exception)null));
Assert.Throws<ArgumentNullException>(
() => ex = new AggregateException("message", (IEnumerable<Exception>)null));
Assert.Throws<ArgumentException>(
() => ex = new AggregateException("message", new[] { new Exception(), null }));
}
[Fact]
public static void BaseExceptions()
{
AggregateException ex = new AggregateException();
Assert.Equal(ex.GetBaseException(), ex);
Exception[] innerExceptions = new Exception[0];
ex = new AggregateException(innerExceptions);
Assert.Equal(ex.GetBaseException(), ex);
innerExceptions = new Exception[1] { new AggregateException() };
ex = new AggregateException(innerExceptions);
Assert.Equal(ex.GetBaseException(), innerExceptions[0]);
innerExceptions = new Exception[2] { new AggregateException(), new AggregateException() };
ex = new AggregateException(innerExceptions);
Assert.Equal(ex.GetBaseException(), ex);
}
[Fact]
public static void Handle()
{
AggregateException ex = new AggregateException();
ex = new AggregateException(new[] { new ArgumentException(), new ArgumentException(), new ArgumentException() });
int handledCount = 0;
ex.Handle((e) =>
{
if (e is ArgumentException)
{
handledCount++;
return true;
}
return false;
});
Assert.Equal(handledCount, ex.InnerExceptions.Count);
}
[Fact]
public static void HandleInvalidCases()
{
AggregateException ex = new AggregateException();
Assert.Throws<ArgumentNullException>(() => ex.Handle(null));
ex = new AggregateException(new[] { new Exception(), new ArgumentException(), new ArgumentException() });
int handledCount = 0;
Assert.Throws<AggregateException>(
() => ex.Handle((e) =>
{
if (e is ArgumentException)
{
handledCount++;
return true;
}
return false;
}));
}
// Validates that flattening (including recursive) works.
[Fact]
public static void Flatten()
{
Exception exceptionA = new Exception("A");
Exception exceptionB = new Exception("B");
Exception exceptionC = new Exception("C");
AggregateException aggExceptionBase = new AggregateException(exceptionA, exceptionB, exceptionC);
// Verify flattening one with another.
// > Flattening (no recursion)...
AggregateException flattened1 = aggExceptionBase.Flatten();
Exception[] expected1 = new Exception[] {
exceptionA, exceptionB, exceptionC
};
Assert.Equal(expected1, flattened1.InnerExceptions);
// Verify flattening one with another, accounting for recursion.
AggregateException aggExceptionRecurse = new AggregateException(aggExceptionBase, aggExceptionBase);
AggregateException flattened2 = aggExceptionRecurse.Flatten();
Exception[] expected2 = new Exception[] {
exceptionA, exceptionB, exceptionC, exceptionA, exceptionB, exceptionC,
};
Assert.Equal(expected2, flattened2.InnerExceptions);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netstandard1.5;
netstandard;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,255 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading.Tasks;
using System.Threading;
using Xunit;
using System.Collections.Generic;
using System.Diagnostics;
namespace TaskCoverage
{
public class Coverage
{
// Regression test: Validates that tasks can wait on int.MaxValue without assertion.
[Fact]
public static void TaskWait_MaxInt32()
{
Task t = Task.Delay(1);
Debug.WriteLine("Wait with int.Maxvalue");
Task.WaitAll(new Task[] { t }, int.MaxValue);
}
//EH
[Fact]
[OuterLoop]
public static void TaskContinuation()
{
int taskCount = Environment.ProcessorCount;
int maxDOP = Int32.MaxValue;
int maxNumberExecutionsPerTask = 1;
int data = 0;
Task[] allTasks = new Task[taskCount + 1];
CancellationTokenSource[] cts = new CancellationTokenSource[taskCount + 1];
for (int i = 0; i <= taskCount; i++)
{
cts[i] = new CancellationTokenSource();
}
CancellationTokenSource cts2 = new CancellationTokenSource();
ConcurrentExclusiveSchedulerPair scheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, maxDOP, maxNumberExecutionsPerTask);
for (int i = 0; i <= taskCount; i++)
{
int j = i;
allTasks[i] = new Task(() =>
{
new TaskFactory(TaskScheduler.Current).StartNew(() => { }).
ContinueWith((task, o) =>
{
int d = (int)o;
Interlocked.Add(ref data, d);
}, j).
ContinueWith((task, o) =>
{
int d = (int)o;
Interlocked.Add(ref data, d);
cts[d].Cancel();
if (d <= taskCount)
{
throw new OperationCanceledException(cts[d].Token);
}
return "Done";
}, j, cts[j].Token).
ContinueWith((task, o) =>
{
int d = (int)o;
Interlocked.Add(ref data, d);
}, j, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, TaskScheduler.Default).Wait(Int32.MaxValue - 1, cts2.Token);
});
allTasks[i].Start(scheduler.ConcurrentScheduler);
}
Task.WaitAll(allTasks, int.MaxValue - 1, CancellationToken.None);
Debug.WriteLine("Tasks ended: result {0}", data);
Task completion = scheduler.Completion;
scheduler.Complete();
completion.Wait();
int expectedResult = 3 * taskCount * (taskCount + 1) / 2;
Assert.Equal(expectedResult, data);
Assert.NotEqual(TaskScheduler.Default.Id, scheduler.ConcurrentScheduler.Id);
Assert.NotEqual(TaskScheduler.Default.Id, scheduler.ExclusiveScheduler.Id);
}
/// <summary>
/// Test various Task.WhenAll and Wait overloads - EH
/// </summary>
[Fact]
public static void TaskWaitWithCTS()
{
ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent mreCont = new ManualResetEvent(false);
CancellationTokenSource cts = new CancellationTokenSource();
int? taskId1 = 0; int? taskId2 = 0;
int? taskId12 = 0; int? taskId22 = 0;
Task t1 = Task.Factory.StartNew(() => { mre.WaitOne(); taskId1 = Task.CurrentId; });
Task t2 = Task.Factory.StartNew(() => { mre.WaitOne(); taskId2 = Task.CurrentId; cts.Cancel(); });
List<Task<int?>> whenAllTaskResult = new List<Task<int?>>();
List<Task> whenAllTask = new List<Task>();
whenAllTask.Add(t1); whenAllTask.Add(t2);
Task<int> contTask = Task.WhenAll(whenAllTask).ContinueWith<int>(
(task) =>
{
// when task1 ends, the token will be cancelled
// move the continuation task in cancellation state
if (cts.IsCancellationRequested) { throw new OperationCanceledException(cts.Token); }
return 0;
}, cts.Token);
contTask.ContinueWith((task) => { mreCont.Set(); });
whenAllTaskResult.Add(Task<int?>.Factory.StartNew((o) => { mre.WaitOne((int)o); return Task.CurrentId; }, 10));
whenAllTaskResult.Add(Task<int?>.Factory.StartNew((o) => { mre.WaitOne((int)o); return Task.CurrentId; }, 10));
t1.Wait(5, cts.Token);
Task.WhenAll(whenAllTaskResult).ContinueWith((task) => { taskId12 = task.Result[0]; taskId22 = task.Result[1]; mre.Set(); });
// Task 2 calls CancellationTokenSource.Cancel. Thus, expect and not fail for System.OperationCanceledException being thrown.
try
{
t2.Wait(cts.Token);
}
catch (System.OperationCanceledException) { } // expected, do nothing
Assert.NotEqual<int?>(taskId1, taskId2);
Assert.NotEqual<int?>(taskId12, taskId22);
Debug.WriteLine("Waiting on continuation task that should move into the cancelled state.");
mreCont.WaitOne();
Assert.True(contTask.Status == TaskStatus.Canceled, "Task status is not correct");
}
/// <summary>
/// test WaitAny and when Any overloads
/// </summary>
[Fact]
public static void TaskWaitAny_WhenAny()
{
ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent mre2 = new ManualResetEvent(false);
CancellationTokenSource cts = new CancellationTokenSource();
Task t1 = Task.Factory.StartNew(() => { mre.WaitOne(); });
Task t2 = Task.Factory.StartNew(() => { mre.WaitOne(); });
Task<int?> t11 = Task.Factory.StartNew(() => { mre2.WaitOne(); return Task.CurrentId; });
Task<int?> t21 = Task.Factory.StartNew(() => { mre2.WaitOne(); return Task.CurrentId; });
//waitAny with token and timeout
Task[] waitAny = new Task[] { t1, t2 };
int timeout = Task.WaitAny(waitAny, 1, cts.Token);
//task whenany
Task.Factory.StartNew(() => { Task.Delay(20); mre.Set(); });
List<Task> whenAnyTask = new List<Task>(); whenAnyTask.Add(t1); whenAnyTask.Add(t2);
List<Task<int?>> whenAnyTaskResult = new List<Task<int?>>(); whenAnyTaskResult.Add(t11); whenAnyTaskResult.Add(t21);
//task<tresult> whenany
int? taskId = 0; //this will be set to the first task<int?> ID that ends
Task waitOnIt = Task.WhenAny(whenAnyTaskResult).ContinueWith((task) => { taskId = task.Result.Result; });
Task.WhenAny(whenAnyTask).ContinueWith((task) => { mre2.Set(); });
Debug.WriteLine("Wait on the scenario to finish");
waitOnIt.Wait();
Assert.Equal<int>(-1, timeout);
Assert.Equal<int>(t11.Id, t11.Result.Value);
Assert.Equal<int>(t21.Id, t21.Result.Value);
bool whenAnyVerification = taskId == t11.Id || taskId == t21.Id;
Assert.True(whenAnyVerification, string.Format("The id for whenAny is not correct expected to be {0} or {1} and it is {2}", t11.Id, t21.Id, taskId));
}
[Fact]
public static void CancellationTokenRegitration()
{
ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent mre2 = new ManualResetEvent(false);
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register((o) => { mre.Set(); }, 1, true);
cts.CancelAfter(5);
Debug.WriteLine("Wait on the scenario to finish");
mre.WaitOne();
}
/// <summary>
/// verify that the taskawaiter.UnsafeOnCompleted is invoked
/// </summary>
[Fact]
public static void TaskAwaiter()
{
ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent mre2 = new ManualResetEvent(false);
ManualResetEvent mre3 = new ManualResetEvent(false);
Task t1 = Task.Factory.StartNew(() => { mre.WaitOne(); });
Task<int> t11 = Task.Factory.StartNew(() => { mre.WaitOne(); return 1; });
t1.GetAwaiter().UnsafeOnCompleted(() => { mre2.Set(); });
t11.GetAwaiter().UnsafeOnCompleted(() => { mre3.Set(); });
mre.Set();
Debug.WriteLine("Wait on the scenario to finish");
mre2.WaitOne(); mre3.WaitOne();
}
/// <summary>
/// verify that the taskawaiter.UnsafeOnCompleted is invoked
/// </summary>
[Fact]
public static void TaskConfigurableAwaiter()
{
ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent mre2 = new ManualResetEvent(false);
ManualResetEvent mre3 = new ManualResetEvent(false);
Task t1 = Task.Factory.StartNew(() => { mre.WaitOne(); });
Task<int> t11 = Task.Factory.StartNew(() => { mre.WaitOne(); return 1; });
t1.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(() => { mre2.Set(); });
t11.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(() => { mre3.Set(); });
mre.Set();
Debug.WriteLine("Wait on the scenario to finish");
mre2.WaitOne(); mre3.WaitOne();
}
/// <summary>
/// FromAsync testing: Not supported in .NET Native
/// </summary>
[Fact]
public static void FromAsync()
{
Task emptyTask = new Task(() => { });
ManualResetEvent mre1 = new ManualResetEvent(false);
ManualResetEvent mre2 = new ManualResetEvent(false);
Task.Factory.FromAsync(emptyTask, (iar) => { mre1.Set(); }, TaskCreationOptions.None, TaskScheduler.Current);
Task<int>.Factory.FromAsync(emptyTask, (iar) => { mre2.Set(); return 1; }, TaskCreationOptions.None, TaskScheduler.Current);
emptyTask.Start();
Debug.WriteLine("Wait on the scenario to finish");
mre1.WaitOne();
mre2.WaitOne();
}
}
}

View File

@@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
using System;
using System.Threading;
namespace System.Threading.Tasks.Tests
{
public static class OperationCanceledExceptionTests
{
[Fact]
public static void BasicConstructors()
{
CancellationToken ct1 = new CancellationTokenSource().Token;
OperationCanceledException ex1 = new OperationCanceledException(ct1);
Assert.Equal(ct1, ex1.CancellationToken);
CancellationToken ct2 = new CancellationTokenSource().Token;
OperationCanceledException ex2 = new OperationCanceledException("message", ct2);
Assert.Equal(ct2, ex2.CancellationToken);
CancellationToken ct3 = new CancellationTokenSource().Token;
OperationCanceledException ex3 = new OperationCanceledException("message", new Exception("inner"), ct3);
Assert.Equal(ct3, ex3.CancellationToken);
}
}
}

View File

@@ -0,0 +1,394 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Xunit;
namespace System.Threading.Tasks.Tests
{
public class TaskAwaiterTests
{
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(false, null)]
[InlineData(true, false)]
[InlineData(true, true)]
[InlineData(true, null)]
public static void OnCompleted_CompletesInAnotherSynchronizationContext(bool generic, bool? continueOnCapturedContext)
{
SynchronizationContext origCtx = SynchronizationContext.Current;
try
{
// Create a context that tracks operations, and set it as current
var validateCtx = new ValidateCorrectContextSynchronizationContext();
Assert.Equal(0, validateCtx.PostCount);
SynchronizationContext.SetSynchronizationContext(validateCtx);
// Create a not-completed task and get an awaiter for it
var mres = new ManualResetEventSlim();
var tcs = new TaskCompletionSource<object>();
// Hook up a callback
bool postedInContext = false;
Action callback = () =>
{
postedInContext = ValidateCorrectContextSynchronizationContext.IsPostedInContext;
mres.Set();
};
if (generic)
{
if (continueOnCapturedContext.HasValue) tcs.Task.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback);
else tcs.Task.GetAwaiter().OnCompleted(callback);
}
else
{
if (continueOnCapturedContext.HasValue) ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback);
else ((Task)tcs.Task).GetAwaiter().OnCompleted(callback);
}
Assert.False(mres.IsSet, "Callback should not yet have run.");
// Complete the task in another context and wait for the callback to run
Task.Run(() => tcs.SetResult(null));
mres.Wait();
// Validate the callback ran and in the correct context
bool shouldHavePosted = !continueOnCapturedContext.HasValue || continueOnCapturedContext.Value;
Assert.Equal(shouldHavePosted ? 1 : 0, validateCtx.PostCount);
Assert.Equal(shouldHavePosted, postedInContext);
}
finally
{
// Reset back to the original context
SynchronizationContext.SetSynchronizationContext(origCtx);
}
}
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(false, null)]
[InlineData(true, false)]
[InlineData(true, true)]
[InlineData(true, null)]
public static void OnCompleted_CompletesInAnotherTaskScheduler(bool generic, bool? continueOnCapturedContext)
{
SynchronizationContext origCtx = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null); // get off xunit's SynchronizationContext to avoid interactions with await
var quwi = new QUWITaskScheduler();
RunWithSchedulerAsCurrent(quwi, delegate
{
Assert.True(TaskScheduler.Current == quwi, "Expected to be on target scheduler");
// Create the not completed task and get its awaiter
var mres = new ManualResetEventSlim();
var tcs = new TaskCompletionSource<object>();
// Hook up the callback
bool ranOnScheduler = false;
Action callback = () =>
{
ranOnScheduler = (TaskScheduler.Current == quwi);
mres.Set();
};
if (generic)
{
if (continueOnCapturedContext.HasValue) tcs.Task.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback);
else tcs.Task.GetAwaiter().OnCompleted(callback);
}
else
{
if (continueOnCapturedContext.HasValue) ((Task)tcs.Task).ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(callback);
else ((Task)tcs.Task).GetAwaiter().OnCompleted(callback);
}
Assert.False(mres.IsSet, "Callback should not yet have run.");
// Complete the task in another scheduler and wait for the callback to run
Task.Run(delegate { tcs.SetResult(null); });
mres.Wait();
// Validate the callback ran on the right scheduler
bool shouldHaveRunOnScheduler = !continueOnCapturedContext.HasValue || continueOnCapturedContext.Value;
Assert.Equal(shouldHaveRunOnScheduler, ranOnScheduler);
});
}
finally
{
SynchronizationContext.SetSynchronizationContext(origCtx);
}
}
[Fact]
public static void GetResult_Completed_Success()
{
Task task = Task.CompletedTask;
task.GetAwaiter().GetResult();
task.ConfigureAwait(false).GetAwaiter().GetResult();
task.ConfigureAwait(true).GetAwaiter().GetResult();
const string expectedResult = "42";
Task<string> taskOfString = Task.FromResult(expectedResult);
Assert.Equal(expectedResult, taskOfString.GetAwaiter().GetResult());
Assert.Equal(expectedResult, taskOfString.ConfigureAwait(false).GetAwaiter().GetResult());
Assert.Equal(expectedResult, taskOfString.ConfigureAwait(true).GetAwaiter().GetResult());
}
[OuterLoop]
[Fact]
public static void GetResult_NotCompleted_BlocksUntilCompletion()
{
var tcs = new TaskCompletionSource<bool>();
// Kick off tasks that should all block
var tasks = new[] {
Task.Run(() => tcs.Task.GetAwaiter().GetResult()),
Task.Run(() => ((Task)tcs.Task).GetAwaiter().GetResult()),
Task.Run(() => tcs.Task.ConfigureAwait(false).GetAwaiter().GetResult()),
Task.Run(() => ((Task)tcs.Task).ConfigureAwait(false).GetAwaiter().GetResult())
};
Assert.Equal(-1, Task.WaitAny(tasks, 100)); // "Tasks should not have completed"
// Now complete the tasks, after which all the tasks should complete successfully.
tcs.SetResult(true);
Task.WaitAll(tasks);
}
[Fact]
public static void GetResult_CanceledTask_ThrowsCancellationException()
{
// Validate cancellation
Task<string> canceled = Task.FromCanceled<string>(new CancellationToken(true));
// Task.GetAwaiter and Task<T>.GetAwaiter
Assert.Throws<TaskCanceledException>(() => ((Task)canceled).GetAwaiter().GetResult());
Assert.Throws<TaskCanceledException>(() => canceled.GetAwaiter().GetResult());
// w/ ConfigureAwait false and true
Assert.Throws<TaskCanceledException>(() => ((Task)canceled).ConfigureAwait(false).GetAwaiter().GetResult());
Assert.Throws<TaskCanceledException>(() => ((Task)canceled).ConfigureAwait(true).GetAwaiter().GetResult());
Assert.Throws<TaskCanceledException>(() => canceled.ConfigureAwait(false).GetAwaiter().GetResult());
Assert.Throws<TaskCanceledException>(() => canceled.ConfigureAwait(true).GetAwaiter().GetResult());
}
[Fact]
public static void GetResult_FaultedTask_OneException_ThrowsOriginalException()
{
var exception = new ArgumentException("uh oh");
Task<string> task = Task.FromException<string>(exception);
// Task.GetAwaiter and Task<T>.GetAwaiter
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.GetAwaiter().GetResult()));
// w/ ConfigureAwait false and true
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).ConfigureAwait(false).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).ConfigureAwait(true).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.ConfigureAwait(false).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.ConfigureAwait(true).GetAwaiter().GetResult()));
}
[Fact]
public static void GetResult_FaultedTask_MultipleExceptions_ThrowsFirstException()
{
var exception = new ArgumentException("uh oh");
var tcs = new TaskCompletionSource<string>();
tcs.SetException(new Exception[] { exception, new InvalidOperationException("uh oh") });
Task<string> task = tcs.Task;
// Task.GetAwaiter and Task<T>.GetAwaiter
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.GetAwaiter().GetResult()));
// w/ ConfigureAwait false and true
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).ConfigureAwait(false).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => ((Task)task).ConfigureAwait(true).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.ConfigureAwait(false).GetAwaiter().GetResult()));
Assert.Same(exception, Assert.Throws<ArgumentException>(() => task.ConfigureAwait(true).GetAwaiter().GetResult()));
}
[Fact]
public static void AwaiterAndAwaitableEquality()
{
var completed = new TaskCompletionSource<string>();
Task task = completed.Task;
// TaskAwaiter
task.GetAwaiter().Equals(task.GetAwaiter());
// ConfiguredTaskAwaitable
Assert.Equal(task.ConfigureAwait(false), task.ConfigureAwait(false));
Assert.NotEqual(task.ConfigureAwait(false), task.ConfigureAwait(true));
Assert.NotEqual(task.ConfigureAwait(true), task.ConfigureAwait(false));
// ConfiguredTaskAwaitable<T>
Assert.Equal(task.ConfigureAwait(false), task.ConfigureAwait(false));
Assert.NotEqual(task.ConfigureAwait(false), task.ConfigureAwait(true));
Assert.NotEqual(task.ConfigureAwait(true), task.ConfigureAwait(false));
// ConfiguredTaskAwaitable.ConfiguredTaskAwaiter
Assert.Equal(task.ConfigureAwait(false).GetAwaiter(), task.ConfigureAwait(false).GetAwaiter());
Assert.NotEqual(task.ConfigureAwait(false).GetAwaiter(), task.ConfigureAwait(true).GetAwaiter());
Assert.NotEqual(task.ConfigureAwait(true).GetAwaiter(), task.ConfigureAwait(false).GetAwaiter());
// ConfiguredTaskAwaitable<T>.ConfiguredTaskAwaiter
Assert.Equal(task.ConfigureAwait(false).GetAwaiter(), task.ConfigureAwait(false).GetAwaiter());
Assert.NotEqual(task.ConfigureAwait(false).GetAwaiter(), task.ConfigureAwait(true).GetAwaiter());
Assert.NotEqual(task.ConfigureAwait(true).GetAwaiter(), task.ConfigureAwait(false).GetAwaiter());
}
[Fact]
public static void BaseSynchronizationContext_SameAsNoSynchronizationContext()
{
var quwi = new QUWITaskScheduler();
SynchronizationContext origCtx = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
RunWithSchedulerAsCurrent(quwi, delegate
{
ManualResetEventSlim mres = new ManualResetEventSlim();
var tcs = new TaskCompletionSource<object>();
var awaiter = ((Task)tcs.Task).GetAwaiter();
bool ranOnScheduler = false;
bool ranWithoutSyncCtx = false;
awaiter.OnCompleted(() =>
{
ranOnScheduler = (TaskScheduler.Current == quwi);
ranWithoutSyncCtx = SynchronizationContext.Current == null;
mres.Set();
});
Assert.False(mres.IsSet, "Callback should not yet have run.");
Task.Run(delegate { tcs.SetResult(null); });
mres.Wait();
Assert.True(ranOnScheduler, "Should have run on scheduler");
Assert.True(ranWithoutSyncCtx, "Should have run with a null sync ctx");
});
}
finally
{
SynchronizationContext.SetSynchronizationContext(origCtx);
}
}
[Theory]
[MemberData(nameof(CanceledTasksAndExpectedCancellationExceptions))]
public static void OperationCanceledException_PropagatesThroughCanceledTask(int lineNumber, Task task, OperationCanceledException expected)
{
var caught = Assert.ThrowsAny<OperationCanceledException>(() => task.GetAwaiter().GetResult());
Assert.Same(expected, caught);
}
public static IEnumerable<object[]> CanceledTasksAndExpectedCancellationExceptions()
{
var cts = new CancellationTokenSource();
var oce = new OperationCanceledException(cts.Token);
// Scheduled Task
Task<int> generic = Task.Run<int>(new Func<int>(() =>
{
cts.Cancel();
throw oce;
}), cts.Token);
yield return new object[] { LineNumber(), generic, oce };
Task nonGeneric = generic;
// WhenAll Task and Task<int>
yield return new object[] { LineNumber(), Task.WhenAll(generic), oce };
yield return new object[] { LineNumber(), Task.WhenAll(generic, Task.FromResult(42)), oce };
yield return new object[] { LineNumber(), Task.WhenAll(Task.FromResult(42), generic), oce };
yield return new object[] { LineNumber(), Task.WhenAll(generic, generic, generic), oce };
yield return new object[] { LineNumber(), Task.WhenAll(nonGeneric), oce };
yield return new object[] { LineNumber(), Task.WhenAll(nonGeneric, Task.FromResult(42)), oce };
yield return new object[] { LineNumber(), Task.WhenAll(Task.FromResult(42), nonGeneric), oce };
yield return new object[] { LineNumber(), Task.WhenAll(nonGeneric, nonGeneric, nonGeneric), oce };
// Task.Run Task and Task<int> with unwrapping
yield return new object[] { LineNumber(), Task.Run(() => generic), oce };
yield return new object[] { LineNumber(), Task.Run(() => nonGeneric), oce };
// A FromAsync Task and Task<int>
yield return new object[] { LineNumber(), Task.Factory.FromAsync(generic, new Action<IAsyncResult>(ar => { throw oce; })), oce };
yield return new object[] { LineNumber(), Task<int>.Factory.FromAsync(nonGeneric, new Func<IAsyncResult, int>(ar => { throw oce; })), oce };
// AsyncTaskMethodBuilder
var atmb = new AsyncTaskMethodBuilder();
atmb.SetException(oce);
yield return new object[] { LineNumber(), atmb.Task, oce };
}
private static int LineNumber([CallerLineNumber]int lineNumber = 0) => lineNumber;
private class ValidateCorrectContextSynchronizationContext : SynchronizationContext
{
[ThreadStatic]
internal static bool IsPostedInContext;
internal int PostCount;
internal int SendCount;
public override void Post(SendOrPostCallback d, object state)
{
Interlocked.Increment(ref PostCount);
Task.Run(() =>
{
try
{
IsPostedInContext = true;
d(state);
}
finally
{
IsPostedInContext = false;
}
});
}
public override void Send(SendOrPostCallback d, object state)
{
Interlocked.Increment(ref SendCount);
d(state);
}
}
/// <summary>A scheduler that queues to the TP and tracks the number of times QueueTask and TryExecuteTaskInline are invoked.</summary>
private class QUWITaskScheduler : TaskScheduler
{
private int _queueTaskCount;
private int _tryExecuteTaskInlineCount;
public int QueueTaskCount { get { return _queueTaskCount; } }
public int TryExecuteTaskInlineCount { get { return _tryExecuteTaskInlineCount; } }
protected override IEnumerable<Task> GetScheduledTasks() { return null; }
protected override void QueueTask(Task task)
{
Interlocked.Increment(ref _queueTaskCount);
Task.Run(() => TryExecuteTask(task));
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
Interlocked.Increment(ref _tryExecuteTaskInlineCount);
return TryExecuteTask(task);
}
}
/// <summary>Runs the action with TaskScheduler.Current equal to the specified scheduler.</summary>
private static void RunWithSchedulerAsCurrent(TaskScheduler scheduler, Action action)
{
var t = new Task(action);
t.RunSynchronously(scheduler);
t.GetAwaiter().GetResult();
}
}
}

View File

@@ -0,0 +1,202 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Xunit;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace System.Threading.Tasks.Tests
{
public class YieldAwaitableTests
{
// awaiting Task.Yield
[Fact]
public static void RunAsyncYieldAwaiterTests()
{
// Test direct usage works even though it's not encouraged
{
for (int i = 0; i < 2; i++)
{
SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext());
var ya = i == 0 ? new YieldAwaitable.YieldAwaiter() : new YieldAwaitable().GetAwaiter();
var mres = new ManualResetEventSlim();
Assert.False(ya.IsCompleted, "RunAsyncYieldAwaiterTests > FAILURE. YieldAwaiter.IsCompleted should always be false.");
ya.OnCompleted(() =>
{
Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, "RunAsyncYieldAwaiterTests > FAILURE. Expected to post in target context.");
mres.Set();
});
mres.Wait();
ya.GetResult();
SynchronizationContext.SetSynchronizationContext(null);
}
}
{
// Yield when there's a current sync context
SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext());
var ya = Task.Yield().GetAwaiter();
try { ya.GetResult(); }
catch
{
Assert.True(false, string.Format("RunAsyncYieldAwaiterTests > FAILURE. YieldAwaiter.GetResult threw inappropriately"));
}
var mres = new ManualResetEventSlim();
Assert.False(ya.IsCompleted, "RunAsyncYieldAwaiterTests > FAILURE. YieldAwaiter.IsCompleted should always be false.");
ya.OnCompleted(() =>
{
Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Expected to post in target context.");
mres.Set();
});
mres.Wait();
ya.GetResult();
SynchronizationContext.SetSynchronizationContext(null);
}
{
// Yield when there's a current TaskScheduler
Task.Factory.StartNew(() =>
{
try
{
var ya = Task.Yield().GetAwaiter();
try { ya.GetResult(); }
catch
{
Assert.True(false, string.Format(" > FAILURE. YieldAwaiter.GetResult threw inappropriately"));
}
var mres = new ManualResetEventSlim();
Assert.False(ya.IsCompleted, " > FAILURE. YieldAwaiter.IsCompleted should always be false.");
ya.OnCompleted(() =>
{
Assert.True(TaskScheduler.Current is QUWITaskScheduler, " > FAILURE. Expected to queue into target scheduler.");
mres.Set();
});
mres.Wait();
ya.GetResult();
}
catch { Assert.True(false, string.Format(" > FAILURE. Unexpected exception from Yield")); }
}, CancellationToken.None, TaskCreationOptions.None, new QUWITaskScheduler()).Wait();
}
{
// Yield when there's a current TaskScheduler and SynchronizationContext.Current is the base SynchronizationContext
Task.Factory.StartNew(() =>
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
try
{
var ya = Task.Yield().GetAwaiter();
try { ya.GetResult(); }
catch
{
Assert.True(false, string.Format(" > FAILURE. YieldAwaiter.GetResult threw inappropriately"));
}
var mres = new ManualResetEventSlim();
Assert.False(ya.IsCompleted, " > FAILURE. YieldAwaiter.IsCompleted should always be false.");
ya.OnCompleted(() =>
{
Assert.True(TaskScheduler.Current is QUWITaskScheduler, " > FAILURE. Expected to queue into target scheduler.");
mres.Set();
});
mres.Wait();
ya.GetResult();
}
catch { Assert.True(false, string.Format(" > FAILURE. Unexpected exception from Yield")); }
SynchronizationContext.SetSynchronizationContext(null);
}, CancellationToken.None, TaskCreationOptions.None, new QUWITaskScheduler()).Wait();
}
{
// OnCompleted grabs the current context, not Task.Yield nor GetAwaiter
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var ya = Task.Yield().GetAwaiter();
SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext());
try { ya.GetResult(); }
catch
{
Assert.True(false, string.Format(" > FAILURE. YieldAwaiter.GetResult threw inappropriately"));
}
var mres = new ManualResetEventSlim();
Assert.False(ya.IsCompleted, " > FAILURE. YieldAwaiter.IsCompleted should always be false.");
ya.OnCompleted(() =>
{
Assert.True(ValidateCorrectContextSynchronizationContext.IsPostedInContext, " > FAILURE. Expected to post in target context.");
mres.Set();
});
mres.Wait();
ya.GetResult();
SynchronizationContext.SetSynchronizationContext(null);
}
}
// awaiting Task.Yield
[Fact]
public static void RunAsyncYieldAwaiterTests_Negative()
{
// Yield when there's a current sync context
SynchronizationContext.SetSynchronizationContext(new ValidateCorrectContextSynchronizationContext());
var ya = Task.Yield().GetAwaiter();
Assert.Throws<ArgumentNullException>(() => { ya.OnCompleted(null); });
}
#region Helper Methods / Classes
private class ValidateCorrectContextSynchronizationContext : SynchronizationContext
{
[ThreadStatic]
internal static bool IsPostedInContext;
internal int PostCount;
internal int SendCount;
public override void Post(SendOrPostCallback d, object state)
{
Interlocked.Increment(ref PostCount);
Task.Run(() =>
{
IsPostedInContext = true;
d(state);
IsPostedInContext = false;
});
}
public override void Send(SendOrPostCallback d, object state)
{
Interlocked.Increment(ref SendCount);
d(state);
}
}
/// <summary>A scheduler that queues to the TP and tracks the number of times QueueTask and TryExecuteTaskInline are invoked.</summary>
private class QUWITaskScheduler : TaskScheduler
{
private int _queueTaskCount;
private int _tryExecuteTaskInlineCount;
public int QueueTaskCount { get { return _queueTaskCount; } }
public int TryExecuteTaskInlineCount { get { return _tryExecuteTaskInlineCount; } }
protected override IEnumerable<Task> GetScheduledTasks() { return null; }
protected override void QueueTask(Task task)
{
Interlocked.Increment(ref _queueTaskCount);
Task.Run(() => TryExecuteTask(task));
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
Interlocked.Increment(ref _tryExecuteTaskInlineCount);
return TryExecuteTask(task);
}
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More