Skip to content

Commit 075e93e

Browse files
authored
Release/v1.0 (#3)
v1.0 Preview 1
1 parent 42f103c commit 075e93e

41 files changed

Lines changed: 6897 additions & 2 deletions

Some content is hidden

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

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 Nikos Sarris
3+
Copyright (c) 2020 Nikos Sarris
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

ParallelTasks.sln

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29324.140
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ParallelTasks", "src\ParallelTasks\ParallelTasks.csproj", "{3D390A6F-A7F2-4C93-A5A4-F7D1EA69E49B}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ParallelTasks.Tests", "test\ParallelTasks.Tests\ParallelTasks.Tests.csproj", "{19F30F88-BFBF-4844-985E-9224863E1369}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1B22EE15-0C53-4D9A-A0A2-2F0CBD9A2387}"
11+
ProjectSection(SolutionItems) = preProject
12+
LICENSE = LICENSE
13+
README.md = README.md
14+
version.props = version.props
15+
EndProjectSection
16+
EndProject
17+
Global
18+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
19+
Debug|Any CPU = Debug|Any CPU
20+
Release|Any CPU = Release|Any CPU
21+
EndGlobalSection
22+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
23+
{3D390A6F-A7F2-4C93-A5A4-F7D1EA69E49B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{3D390A6F-A7F2-4C93-A5A4-F7D1EA69E49B}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{3D390A6F-A7F2-4C93-A5A4-F7D1EA69E49B}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{3D390A6F-A7F2-4C93-A5A4-F7D1EA69E49B}.Release|Any CPU.Build.0 = Release|Any CPU
27+
{19F30F88-BFBF-4844-985E-9224863E1369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28+
{19F30F88-BFBF-4844-985E-9224863E1369}.Debug|Any CPU.Build.0 = Debug|Any CPU
29+
{19F30F88-BFBF-4844-985E-9224863E1369}.Release|Any CPU.ActiveCfg = Release|Any CPU
30+
{19F30F88-BFBF-4844-985E-9224863E1369}.Release|Any CPU.Build.0 = Release|Any CPU
31+
EndGlobalSection
32+
GlobalSection(SolutionProperties) = preSolution
33+
HideSolutionNode = FALSE
34+
EndGlobalSection
35+
GlobalSection(ExtensibilityGlobals) = postSolution
36+
SolutionGuid = {2C1207AE-0A79-4B68-8864-45A8C1069FA2}
37+
EndGlobalSection
38+
EndGlobal

README.md

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,85 @@
1-
# ParallelTasks
1+
# ParallelTasks
2+
3+
Awaiting multiple tasks using the Task Parallel Library and Task.WhenAll / Task.WhenAny can be too verbose syntactically as you need to assign each task to a variable, await the collection of tasks and then inspect each task individual for exceptions in case an AggregateException is thrown during parallel processing.
4+
5+
The aim of this library is to simplify the syntax of performing parrellel task operations. To achieve this, all tasks handled by ParallelTasks are transformed to Task<ITaskResult> (or any of the ITaskResult interface's generic derivatives). In this way tasks become exceptionless, meaning they all run to completion and any possible exceptions are encapsulated in the resulting ITaskResult, along with any result and the completed task status. In addition, as opposed to Task.WhenAll all results are strongly typed.
6+
7+
The main entry point is Tasks.WhenAll and Tasks.WhenAny to match the original Task.WhenAll and Task.WhenAny. Additionally Tasks.WhenEach is added to support asynchronous enumaration using IAsyncAnumerable (NetStandard 2.0 onwards)
8+
9+
This will effectively transfrom this:
10+
11+
```csharp
12+
var task1 = PerformTask1Async();
13+
var task2 = PerformTask2Async();
14+
var task3 = PerformTask3Async();
15+
16+
try
17+
{
18+
var result = await Task.WhenAll(new [] { task1, task2, task3 });
19+
}
20+
catch(Exception e)
21+
{
22+
if (task1.Exception != null)
23+
{
24+
//Handle error
25+
}
26+
if (task2.Exception != null)
27+
{
28+
//Handle error
29+
}
30+
if (task3.Exception != null)
31+
{
32+
//Handle error
33+
}
34+
}
35+
36+
if (task1.Exception != null
37+
&& task2.Exception != null
38+
&& task2.Exception != null)
39+
{
40+
//Success
41+
}
42+
```
43+
44+
to:
45+
46+
```csharp
47+
var results = await Tasks.WhenAll(
48+
PerformTask1Async()
49+
PerformTask2Async()
50+
PerformTask3Async());
51+
52+
if (results.AllCompletedSuccessfully)
53+
{
54+
//Success
55+
}
56+
else
57+
{
58+
foreach(var taskResult in results.GetFailedOrCanceled()))
59+
{
60+
//Handle task error
61+
}
62+
}
63+
```
64+
65+
or for individual processing:
66+
67+
```csharp
68+
var results = await Tasks.WhenAll(
69+
PerformTask1Async()
70+
PerformTask2Async()
71+
PerformTask3Async());
72+
73+
var (task1Result, task2Result, task3Result) = results.AsTuple();
74+
75+
//Handle each strongly typed result individually
76+
```
77+
78+
Other features include:
79+
- Strongly typed results for WhenAll when awaiting multiple Task<T> with different result Types.
80+
- ITaskResult includes the result if the underlying Task is Task<T>.
81+
- Indexing: All tasks and results are indexed to match result with task/
82+
- Naming: Tasks can be named to match result with task or for logging.
83+
- Producing tasks from an enumerable source, producing results that encapsulate the originating source value.
84+
- DegreeOfParallelism can be set to restrict maximum parallel execution. Overriding this value for debugging is also supported.
85+
- WhenAll results can be returned as a Tuple to provide easily named results.

azure-pipelines.yml

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Starter pipeline
2+
# Start with a minimal pipeline that you can customize to build and deploy your code.
3+
# Add steps that build, run tests, deploy, and more:
4+
# https://aka.ms/yaml
5+
6+
trigger:
7+
branches:
8+
include:
9+
- main
10+
paths:
11+
exclude:
12+
- README.md
13+
pr:
14+
branches:
15+
include:
16+
- main
17+
paths:
18+
exclude:
19+
- README.md
20+
21+
pool:
22+
vmImage: 'windows-latest'
23+
24+
variables:
25+
isRelease: False
26+
isPrerelease: False
27+
projectVersion:
28+
29+
${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
30+
isMain: true
31+
buildConfiguration: 'Release'
32+
${{ if ne(variables['Build.SourceBranch'], 'refs/heads/main') }}:
33+
isMain: false
34+
buildConfiguration: 'Debug'
35+
36+
${{ if startsWith(variables['Build.SourceBranch'], 'refs/pull/') }}:
37+
releaseBuild: $[eq(variables['System.PullRequest.TargetBranch'], 'main')]
38+
isPullRequest: True
39+
isAlphaRelease: $[eq(variables['System.PullRequest.TargetBranch'], 'main')]
40+
${{ if not(startsWith(variables['Build.SourceBranch'], 'refs/pull/')) }}:
41+
releaseBuild: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
42+
isPullRequest: False
43+
isAlphaRelease: False
44+
45+
steps:
46+
47+
- task: Bash@3
48+
displayName: 'Get Version from version.props'
49+
inputs:
50+
targetType: 'inline'
51+
script: |
52+
PROJECT_VERSION_PREFIX="$(grep '<VersionPrefix>' < version.props | sed 's/.*<VersionPrefix>\(.*\)<\/VersionPrefix>/\1/')"
53+
PROJECT_VERSION_SUFFIX="$(grep '<VersionSuffix>' < version.props | sed 's/.*<VersionSuffix>\(.*\)<\/VersionSuffix>/\1/')"
54+
echo "##vso[task.setvariable variable=projectVersionPrefix]$PROJECT_VERSION_PREFIX"
55+
echo "##vso[task.setvariable variable=projectVersionSuffix]$PROJECT_VERSION_SUFFIX"
56+
if [ $ISALPHARELEASE == "False" ]; then
57+
if [ -n "$PROJECT_VERSION_SUFFIX" ]; then
58+
echo "##vso[task.setvariable variable=isPrerelease]True"
59+
echo "##vso[task.setvariable variable=projectVersion]$PROJECT_VERSION_PREFIX-$PROJECT_VERSION_SUFFIX"
60+
else
61+
echo "##vso[task.setvariable variable=isRelease]True"
62+
echo "##vso[task.setvariable variable=projectVersion]$PROJECT_VERSION_PREFIX"
63+
fi
64+
else
65+
echo "##vso[task.setvariable variable=projectVersionSuffix]alpha-$(Build.BuildNumber)"
66+
echo "##vso[task.setvariable variable=projectVersion]$PROJECT_VERSION_PREFIX-alpha-$(Build.BuildNumber)"
67+
fi
68+
69+
- task: Bash@3
70+
condition: true
71+
displayName: 'Log pipeline configuration'
72+
inputs:
73+
targetType: 'inline'
74+
script: |
75+
echo "Source Branch: $(Build.SourceBranch)"
76+
echo "Is Pull Request: $(isPullRequest)"
77+
[ "$(isPullRequest)" == "True" ] && echo "Pull Request Source: $(System.PullRequest.SourceBranch)" && echo "Pull Request Target: $(System.PullRequest.TargetBranch)"
78+
echo "Release Build: $(releaseBuild)"
79+
echo "Stable release: $(isRelease)"
80+
echo "Prerelease: $(isPrerelease)"
81+
echo "Alpha: $(isAlphaRelease)"
82+
echo "Build Configuration: $(buildConfiguration)"
83+
echo "Build Version: $(projectVersion)"
84+
85+
86+
- task: DotNetCoreCLI@2
87+
inputs:
88+
command: 'restore'
89+
projects: '**/*.sln'
90+
displayName: 'Restore packages'
91+
92+
- task: DotNetCoreCLI@2
93+
inputs:
94+
command: 'build'
95+
projects: '**/*.sln'
96+
arguments: '--configuration $(buildConfiguration) --no-restore /property:VersionSuffix="$(projectVersionSuffix)"'
97+
displayName: 'Build'
98+
99+
- task: DotNetCoreCLI@2
100+
inputs:
101+
command: test
102+
projects: '**/*.sln'
103+
arguments: '--configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/'
104+
publishTestResults: true
105+
nobuild: true
106+
displayName: 'Run Tests'
107+
108+
- task: PublishCodeCoverageResults@1
109+
displayName: 'Publish code coverage report'
110+
inputs:
111+
codeCoverageTool: 'Cobertura'
112+
summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage*.cobertura.xml'
113+
114+
- task: DotNetCoreCLI@2
115+
condition: and(succeeded(), eq(variables.releaseBuild, true))
116+
inputs:
117+
command: 'custom'
118+
custom: 'pack'
119+
projects: '**/*.sln'
120+
arguments: '--configuration $(buildConfiguration) --no-restore --no-build --output $(Build.ArtifactStagingDirectory) --version-suffix="$(projectVersionSuffix)"'
121+
displayName: 'Create package'
122+
123+
- task: GitHubRelease@1
124+
displayName: Create Github release
125+
condition: and(succeeded(), eq(variables.releaseBuild, true), or(eq(variables.isRelease, true),eq(variables.isPrerelease, true)))
126+
inputs:
127+
gitHubConnection: 'github.com_nsarris'
128+
repositoryName: 'nsarris/ParallelTasks'
129+
action: 'create'
130+
target: '$(Build.SourceVersion)'
131+
tagSource: 'userSpecifiedTag'
132+
tag: 'v$(projectVersion)'
133+
title: 'v$(projectVersion)'
134+
releaseNotesSource: 'inline'
135+
isPreRelease: $(isPrerelease)
136+
addChangeLog: false
137+
138+
- task: NuGetAuthenticate@0
139+
condition: and(succeeded(), eq(variables.releaseBuild, true))
140+
displayName: 'NuGet Authenticate'
141+
142+
- task: NuGetCommand@2
143+
displayName: Nuget Push (Alpha feed)
144+
condition: and(succeeded(), eq(variables.releaseBuild, true), eq(variables.isAlphaRelease, true))
145+
inputs:
146+
command: 'push'
147+
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
148+
nuGetFeedType: 'internal'
149+
publishVstsFeed: '8bd3f470-a025-4709-944d-71b861c79f14/72a2a01e-ed8d-4409-8a57-aea04fca4b84'
150+
allowPackageConflicts: true
151+
152+
- task: NuGetCommand@2
153+
displayName: Nuget Push (Release feed)
154+
condition: and(succeeded(), eq(variables.releaseBuild, true), or(eq(variables.isRelease, true), eq(variables.isPrerelease, true)))
155+
inputs:
156+
command: 'push'
157+
packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
158+
nuGetFeedType: 'external'
159+
publishFeedCredentials: 'nuget.org_nsarris'

0 commit comments

Comments
 (0)