Upgraded Nuget packages. Added a new For function for executing a for loop in parallel. Added unit tests. Bumped package version to 1.0.2
This commit is contained in:
parent
779ceee2c1
commit
58e2a809a0
@ -11,14 +11,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.11.0" />
|
<PackageReference Include="FluentAssertions" Version="6.12.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="xunit" Version="2.4.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -147,5 +147,41 @@ namespace MontoyaTech.Parallel.Net.Tests
|
|||||||
|
|
||||||
results.Should().Be(5);
|
results.Should().Be(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parallel_For_Odd_Should_Work()
|
||||||
|
{
|
||||||
|
var indexes = new List<long>();
|
||||||
|
|
||||||
|
ParallelTask.For(0, 3, index =>
|
||||||
|
{
|
||||||
|
lock (indexes)
|
||||||
|
indexes.Add(index);
|
||||||
|
}, 2);
|
||||||
|
|
||||||
|
indexes.Count.Should().Be(3);
|
||||||
|
|
||||||
|
for (long i = 0; i < 3; i++)
|
||||||
|
if (!indexes.Contains(i))
|
||||||
|
throw new Exception($"Test failed, missing index: {i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Parallel_For_Even_Should_Work()
|
||||||
|
{
|
||||||
|
var indexes = new List<long>();
|
||||||
|
|
||||||
|
ParallelTask.For(0, 4, index =>
|
||||||
|
{
|
||||||
|
lock (indexes)
|
||||||
|
indexes.Add(index);
|
||||||
|
}, 2);
|
||||||
|
|
||||||
|
indexes.Count.Should().Be(4);
|
||||||
|
|
||||||
|
for (long i = 0; i < 4; i++)
|
||||||
|
if (!indexes.Contains(i))
|
||||||
|
throw new Exception($"Test failed, missing index: {i}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<PackageIcon>Logo_Symbol_Black_Outline.png</PackageIcon>
|
<PackageIcon>Logo_Symbol_Black_Outline.png</PackageIcon>
|
||||||
<RepositoryUrl>https://code.montoyatech.com/MontoyaTech/Parallel.Net</RepositoryUrl>
|
<RepositoryUrl>https://code.montoyatech.com/MontoyaTech/Parallel.Net</RepositoryUrl>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -216,6 +216,63 @@ namespace MontoyaTech.Parallel.Net
|
|||||||
throw tasks[i].ThrownException;
|
throw tasks[i].ThrownException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs an action for loop in parallel where index greaterthanorequal start and index lessthan end.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">The starting index.</param>
|
||||||
|
/// <param name="end">The ending index, index is always less than this value.</param>
|
||||||
|
/// <param name="action">The paramter is the index from the loop.</param>
|
||||||
|
/// <param name="maxTasks">The max number of tasks to run in parallel. If null the number of available cores is used. Default is null.</param>
|
||||||
|
/// <param name="timeout">If set this function will return early if the tieout is reached even if the tasks are not done. Default is null.</param>
|
||||||
|
/// <param name="throwOnTimeout">If true an exception will be thrown if a timeout is reached is one was set. Default is true.</param>
|
||||||
|
/// <param name="bubbleExceptions">If true, rethrows any exceptions from the running tasks. Default is true.</param>
|
||||||
|
public static void For(long start, long end, Action<long> action, int? maxTasks = null, TimeSpan? timeout = null, bool throwOnTimeout = true, bool bubbleExceptions = true)
|
||||||
|
{
|
||||||
|
if (start == 0 && end == start)
|
||||||
|
return;
|
||||||
|
else if (start >= end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var tasks = new List<ParallelTask<(long chunkStart, long chunkEnd)>>();
|
||||||
|
|
||||||
|
if (!maxTasks.HasValue)
|
||||||
|
maxTasks = Environment.ProcessorCount;
|
||||||
|
else if (maxTasks <= 0)
|
||||||
|
maxTasks = 1;
|
||||||
|
|
||||||
|
long itemsPerChunk = ((end - start) / (long)maxTasks.Value) + 1;
|
||||||
|
|
||||||
|
long index = start;
|
||||||
|
for (int i = 0; i < maxTasks.Value; i++)
|
||||||
|
{
|
||||||
|
var chunkStart = index;
|
||||||
|
var chunkEnd = index + itemsPerChunk;
|
||||||
|
index += itemsPerChunk;
|
||||||
|
|
||||||
|
if (chunkEnd > end)
|
||||||
|
chunkEnd = end;
|
||||||
|
|
||||||
|
tasks.Add(new ParallelTask<(long chunkStart, long chunkEnd)>(state =>
|
||||||
|
{
|
||||||
|
for (long i = state.chunkStart; i < state.chunkEnd; i++)
|
||||||
|
action(i);
|
||||||
|
}, (chunkStart, chunkEnd)));
|
||||||
|
|
||||||
|
if (index >= end)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tasks.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WhenAll(tasks, timeout, throwOnTimeout);
|
||||||
|
|
||||||
|
if (bubbleExceptions)
|
||||||
|
for (int i = 0; i < tasks.Count; i++)
|
||||||
|
if (tasks[i].Failed && tasks[i].ThrownException != null)
|
||||||
|
throw tasks[i].ThrownException;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a list of tasks and waits until they have been completed or failed and returns the results.
|
/// Runs a list of tasks and waits until they have been completed or failed and returns the results.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user