├── .github └── workflows │ └── bump-version.yml ├── .gitignore ├── IWorkItemState.cs ├── IWorkItemStateTypeless.cs ├── LICENSE ├── NUnitTests ├── ThreadPoolTests.cs └── ThreadingThreadpoolTestObject.cs ├── Properties └── AssemblyInfo.cs ├── SingleThreadRunner.cs ├── ThreadPool.ActionT.cs ├── ThreadPool.FuncT.cs ├── ThreadPool.cs ├── ThreadPooling.csproj ├── ThreadPooling.sln.DotSettings ├── WorkItem.cs ├── WorkItemState.cs ├── WorkItemStateTypeless.cs ├── bin └── Release │ ├── LockFreeQueue.dll │ ├── SplitStopWatch.dll │ ├── ThreadPooling.dll │ ├── Utilities.dll │ └── nunit.framework.dll ├── lib ├── SplitStopWatch.dll └── nunit.framework.dll └── readme.md /.github/workflows/bump-version.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Bump version 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@master 13 | with: 14 | fetch-depth: '0' 15 | - name: Bump version and push tag 16 | uses: anothrNick/github-tag-action@master 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | RELEASE_BRANCHES: master 20 | DEFAULT_BUMP: patch 21 | WITH_V: false 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # git ignore file 2 | #OS junk files 3 | [Tt]humbs.db 4 | *.DS_Store 5 | 6 | #Visual Studio files 7 | *.[Oo]bj 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *.vssscc 13 | *_i.c 14 | *_p.c 15 | *.ncb 16 | *.suo 17 | *.tlb 18 | *.tlh 19 | *.bak 20 | *.[Cc]ache 21 | *.ilk 22 | *.log 23 | *.lib 24 | *.sbr 25 | *.sdf 26 | *.opensdf 27 | *.unsuccessfulbuild 28 | *.cachefile 29 | ipch/ 30 | obj/ 31 | [Bb]in 32 | [Dd]ebug*/ 33 | [Rr]elease*/ 34 | Ankh.NoLoad 35 | 36 | #MonoDevelop 37 | *.pidb 38 | *.userprefs 39 | 40 | #Tooling 41 | _ReSharper*/ 42 | *.resharper 43 | [Tt]est[Rr]esult* 44 | *.sass-cache 45 | 46 | #Project files 47 | [Bb]uild/ 48 | 49 | #Subversion files 50 | .svn 51 | 52 | # Office Temp Files 53 | ~$* 54 | 55 | #NuGet 56 | packages/ 57 | 58 | #ncrunch 59 | *ncrunch* 60 | *crunch*.local.xml 61 | 62 | # visual studio database projects 63 | *.dbmdl 64 | 65 | #Test files 66 | *.testsettings 67 | 68 | ThrobaxTD/Achievements/Achievements.Windows.csproj 69 | ThrobaxTD/EffectQueue/EffectQueue.Windows.csproj 70 | ThrobaxTD/FlockAI/FlockAI.Windows.csproj 71 | ThrobaxTD/InputDevices/InputDevices.Windows.csproj 72 | ThrobaxTD/LightningEngine/LightningEngine.Windows.csproj 73 | ThrobaxTD/Panels/Panels.Windows.csproj 74 | ThrobaxTD/ParticleEngine/ParticleEngine.Windows.csproj 75 | ThrobaxTD/ScreenManagerLibrary/ScreenManagerLibrary.Windows.csproj 76 | ThrobaxTD/SoundSystem/SoundSystem.Windows.csproj 77 | ThrobaxTD/Sprites/Sprites.Windows.csproj 78 | ThrobaxTD/Textures/Textures.Windows.csproj 79 | ThrobaxTD/ThrobaxTD.Windows.sln 80 | ThrobaxTD/ThrobaxTD.Windows.speccache 81 | ThrobaxTD/ThrobaxTD/ThrobaxTD.Windows.csproj 82 | ThrobaxTD/TiledLevel/TiledLevel.Windows.csproj 83 | ThrobaxTD/Utilities/Utilities.Windows.csproj 84 | ThrobaxTD/WindGenerator/WindGenerator.Windows.csproj 85 | ThrobaxTD/Achievements/Achievements.Linux.csproj 86 | ThrobaxTD/EffectQueue/EffectQueue.Linux.csproj 87 | ThrobaxTD/FlockAI/FlockAI.Linux.csproj 88 | ThrobaxTD/InputDevices/InputDevices.Linux.csproj 89 | ThrobaxTD/LightningEngine/LightningEngine.Linux.csproj 90 | ThrobaxTD/Panels/Panels.Linux.csproj 91 | ThrobaxTD/ParticleEngine/ParticleEngine.Linux.csproj 92 | ThrobaxTD/ScreenManagerLibrary/ScreenManagerLibrary.Linux.csproj 93 | ThrobaxTD/SoundSystem/SoundSystem.Linux.csproj 94 | ThrobaxTD/Sprites/Sprites.Linux.csproj 95 | ThrobaxTD/Textures/Textures.Linux.csproj 96 | ThrobaxTD/ThrobaxTD.Linux.sln 97 | ThrobaxTD/ThrobaxTD.Linux.speccache 98 | ThrobaxTD/ThrobaxTD/ThrobaxTD.Linux.csproj 99 | ThrobaxTD/TiledLevel/TiledLevel.Linux.csproj 100 | ThrobaxTD/Utilities/Utilities.Linux.csproj 101 | ThrobaxTD/WindGenerator/WindGenerator.Linux.csproj 102 | *.sln 103 | -------------------------------------------------------------------------------- /IWorkItemState.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System; 29 | 30 | namespace ThreadPooling 31 | { 32 | /// 33 | /// This is an interface for a thread-workItem. 34 | /// 35 | /// The type of the result. 36 | public interface IWorkItemState : IDisposable 37 | { 38 | /// 39 | /// Gets a value indicating whether this instance is completed. 40 | /// 41 | /// 42 | /// true if this instance is completed; otherwise, false. 43 | /// 44 | bool IsStopped { get; } 45 | 46 | /// 47 | /// Is a blocking operation. 48 | /// Gets the result. 49 | /// 50 | /// The result. 51 | T Result { get; } 52 | } 53 | 54 | /// 55 | /// This is an interface for a thread-workItem. 56 | /// 57 | public interface IWorkItemState : IDisposable 58 | { 59 | /// 60 | /// Gets a value indicating whether this instance is completed. 61 | /// 62 | /// 63 | /// true if this instance is completed; otherwise, false. 64 | /// 65 | bool IsStopped { get; } 66 | 67 | /// 68 | /// Is a blocking operation. 69 | /// Waits for the work item to finish. 70 | /// 71 | /// The result. 72 | void Result(); 73 | } 74 | } -------------------------------------------------------------------------------- /IWorkItemStateTypeless.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | namespace ThreadPooling 29 | { 30 | /// 31 | /// An interface for the type-less work-item-state. 32 | /// 33 | public interface IWorkItemStateTypeless : IWorkItemState 34 | { 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /NUnitTests/ThreadPoolTests.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System; 29 | using System.Collections.Generic; 30 | using System.Threading; 31 | using NUnit.Framework; 32 | using SplitStopWatch; 33 | 34 | namespace ThreadPooling.NUnitTests 35 | { 36 | /// 37 | /// Tests for EnqueueWorkItem. 38 | /// 39 | [TestFixture] 40 | [Category("Threading.ThreadPool")] 41 | public class Threading 42 | { 43 | private ThreadPool threadPool; 44 | 45 | /// 46 | /// Initializes this instance. 47 | /// 48 | [SetUp] 49 | public void Init() 50 | { 51 | } 52 | 53 | /// 54 | /// Finishes this instance. 55 | /// 56 | [TearDown] 57 | public void Finish() 58 | { 59 | } 60 | 61 | /// 62 | /// Tests the thread pool. 63 | /// 64 | [Test] 65 | [Category("Threading.ThreadPool")] 66 | public void TestThreadPool() 67 | { 68 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 69 | 70 | var ssw = new SplitStopwatch(); 71 | ssw.Start("starting to enqueue..."); 72 | 73 | var wir1 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 74 | var wir2 = threadPool.EnqueueWorkItem(CalcAverage, new[] {1, 1, 1, 1}); 75 | var wir3 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 76 | var wir4 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 77 | var wir5 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 78 | var wir6 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 79 | var wir7 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 80 | var wir8 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 81 | var wir9 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 82 | var wir10 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 83 | 84 | ssw.Split("all items are enqueued..."); 85 | 86 | var average = wir1.Result; 87 | Assert.AreEqual(average, 3.0); 88 | ssw.Split("we waited for result 1..."); 89 | wir1.Dispose(); 90 | 91 | average = wir2.Result; 92 | Assert.AreEqual(average, 1.0); 93 | ssw.Split("we waited for result 2..."); 94 | wir2.Dispose(); 95 | 96 | average = wir3.Result; 97 | Assert.AreEqual(average, 3.0); 98 | ssw.Split("we waited for result 3..."); 99 | wir3.Dispose(); 100 | 101 | average = wir4.Result; 102 | Assert.AreEqual(average, 3.0); 103 | ssw.Split("we waited for result 4..."); 104 | wir4.Dispose(); 105 | 106 | average = wir5.Result; 107 | Assert.AreEqual(average, 3.0); 108 | ssw.Split("we waited for result 5..."); 109 | wir5.Dispose(); 110 | 111 | average = wir6.Result; 112 | Assert.AreEqual(average, 3.0); 113 | ssw.Split("we waited for result 6..."); 114 | wir6.Dispose(); 115 | 116 | average = wir7.Result; 117 | Assert.AreEqual(average, 3.0); 118 | ssw.Split("we waited for result 7..."); 119 | wir7.Dispose(); 120 | 121 | average = wir8.Result; 122 | Assert.AreEqual(average, 3.0); 123 | ssw.Split("we waited for result 8..."); 124 | wir8.Dispose(); 125 | 126 | average = wir9.Result; 127 | Assert.AreEqual(average, 3.0); 128 | ssw.Split("we waited for result 9..."); 129 | wir9.Dispose(); 130 | 131 | average = wir10.Result; 132 | Assert.AreEqual(average, 3.0); 133 | ssw.Split("we waited for result 10..."); 134 | wir10.Dispose(); 135 | 136 | var wir11 = threadPool.EnqueueWorkItem(CalcAverage, new[] {2, 3, 2, 5}); 137 | average = wir11.Result; 138 | Assert.AreEqual(average, 3.0); 139 | ssw.Split("we waited for result 11..."); 140 | wir11.Dispose(); 141 | 142 | threadPool.ShutDown(); 143 | } 144 | 145 | /// 146 | /// Tests the thread pool. 147 | /// 148 | [Test] 149 | [Category("Threading.ThreadPool")] 150 | public void TestThreadPoolManyThreadsFuncT() 151 | { 152 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 153 | 154 | var wirs = new List>(); 155 | 156 | for (var i = 0; i < 50; i++) 157 | { 158 | var wir = threadPool.EnqueueWorkItem(Not, true); 159 | wirs.Add(wir); 160 | } 161 | 162 | foreach (var workItemState in wirs) 163 | { 164 | var result = workItemState.Result; 165 | workItemState.Dispose(); 166 | 167 | Assert.AreEqual(result, false); 168 | } 169 | 170 | threadPool.ShutDown(); 171 | } 172 | 173 | /// 174 | /// Tests the thread pool. 175 | /// 176 | [Test] 177 | [Category("Threading.ThreadPool")] 178 | public void TestThreadPoolManyWorkItemsSingleThread() 179 | { 180 | threadPool = new ThreadPool(1, "testWorker"); 181 | 182 | var wirs = new List>(); 183 | 184 | for (var i = 0; i < 50; i++) 185 | { 186 | var wir = threadPool.EnqueueWorkItem(Not, i%2 == 1); 187 | wirs.Add(wir); 188 | } 189 | 190 | var anticipatedResult = true; 191 | foreach (var workItemState in wirs) 192 | { 193 | var result = workItemState.Result; 194 | workItemState.Dispose(); 195 | 196 | Assert.AreEqual(result, anticipatedResult); 197 | anticipatedResult = !anticipatedResult; 198 | } 199 | 200 | threadPool.ShutDown(); 201 | } 202 | 203 | /// 204 | /// Tests the thread pool. 205 | /// 206 | [Test] 207 | [Ignore] 208 | [Category("Threading.ThreadPool")] 209 | public void TestThreadPoolManyThreadsActionT() 210 | { 211 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 212 | 213 | var wirs = new List(); 214 | 215 | for (var i = 0; i < 50; i++) 216 | { 217 | var wir = threadPool.EnqueueWorkItem(WriteToConsole, "test"); 218 | wirs.Add(wir); 219 | } 220 | 221 | foreach (var workItemState in wirs) 222 | { 223 | workItemState.Result(); 224 | workItemState.Dispose(); 225 | } 226 | 227 | threadPool.ShutDown(); 228 | } 229 | 230 | /// 231 | /// Tests the thread pool. 232 | /// Tests, if all the enqueued items are only calculated once. 233 | /// 234 | [Test] 235 | [Ignore] 236 | [Category("Threading.ThreadPool")] 237 | public void TestThreadPoolManyThreadsActionTNumberOfCalls() 238 | { 239 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 240 | 241 | var wirs = new List(); 242 | var objects = new List(); 243 | 244 | for (var j = 0; j < 5000; j++) 245 | { 246 | wirs.Clear(); 247 | objects.Clear(); 248 | for (var i = 0; i < 100; i++) 249 | { 250 | var o = new ThreadingThreadpoolTestObject(); 251 | objects.Add(o); 252 | var wir = threadPool.EnqueueWorkItem(o.Call); 253 | wirs.Add(wir); 254 | } 255 | 256 | foreach (var workItemState in wirs) 257 | { 258 | workItemState.Result(); 259 | workItemState.Dispose(); 260 | } 261 | 262 | foreach (var threadingThreadpoolTestObject in objects) 263 | { 264 | Assert.AreEqual(1, threadingThreadpoolTestObject.NumberOfCalls, 265 | "One of the objects has been called " + threadingThreadpoolTestObject.NumberOfCalls + 266 | " times. It was expected to be called once only and exactly once."); 267 | } 268 | } 269 | 270 | threadPool.ShutDown(); 271 | } 272 | 273 | /// 274 | /// Tests the thread pool. 275 | /// 276 | [Test] 277 | [Ignore] 278 | [Category("Threading.ThreadPool")] 279 | public void TestThreadPoolManyThreadsActionTWithCallback() 280 | { 281 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 282 | 283 | var wirs = new List(); 284 | 285 | for (var i = 0; i < 50; i++) 286 | { 287 | var wir = threadPool.EnqueueWorkItem(WriteToConsole, "test", CallbackFunction); 288 | wirs.Add(wir); 289 | } 290 | 291 | foreach (var workItemState in wirs) 292 | { 293 | workItemState.Result(); 294 | workItemState.Dispose(); 295 | } 296 | 297 | threadPool.ShutDown(); 298 | } 299 | 300 | /// 301 | /// Tests the thread pool. 302 | /// 303 | [Test] 304 | [Ignore] 305 | [Category("Threading.ThreadPool")] 306 | public void TestThreadPoolPausedAndResumed() 307 | { 308 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 309 | 310 | var wirs = new List(); 311 | 312 | for (var i = 0; i < 10; i++) 313 | { 314 | if (i == 5) 315 | { 316 | threadPool.Sleep(); 317 | Thread.Sleep(2000); 318 | } 319 | var wir = threadPool.EnqueueWorkItem(WriteToConsole, "test " + (i + 1)); 320 | wirs.Add(wir); 321 | } 322 | 323 | threadPool.Wakeup(); 324 | 325 | foreach (var workItemState in wirs) 326 | { 327 | workItemState.Result(); 328 | workItemState.Dispose(); 329 | } 330 | 331 | threadPool.ShutDown(); 332 | } 333 | 334 | /// 335 | /// Tests the thread pool's performance. 336 | /// Tests without threadpool and with threadpools employing a workerthread-count of one to Environment.ProcessorCount * 337 | /// 2. 338 | /// 339 | [Test] 340 | [Category("Threading.ThreadPool.Performance")] 341 | public void TestThreadPoolPerformance() 342 | { 343 | const int numberOfOperations = 100000; 344 | var ssw = new SplitStopwatch(); 345 | 346 | // Test without any threadPool. 347 | ssw.Start("SINGLE THREADED WITHOUT POOL:"); 348 | for (var i = 0; i < numberOfOperations; i++) 349 | { 350 | CalcAverage(GetNumbersForAverage()); 351 | } 352 | ssw.Stop("Done.", 1); 353 | Console.Out.WriteLine(string.Empty); 354 | ssw.Reset(); 355 | 356 | for (var numberOfWorkerThreads = 1; 357 | numberOfWorkerThreads < Environment.ProcessorCount*2; 358 | numberOfWorkerThreads++) 359 | { 360 | ssw.Start("THREADPOOL (" + numberOfWorkerThreads + " workerThreads):"); 361 | threadPool = new ThreadPool(numberOfWorkerThreads, "testWorker"); 362 | ssw.Split("Starting to enqueue.", 1); 363 | 364 | for (var i = 0; i < numberOfOperations; i++) 365 | { 366 | threadPool.EnqueueWorkItem(CalcAverage, GetNumbersForAverage()); 367 | } 368 | 369 | ssw.Split("All items are enqueued.", 1); 370 | threadPool.WaitForEveryWorkerIdle(); 371 | threadPool.ShutDown(); 372 | 373 | ssw.Stop("Done.", 1); 374 | Console.Out.WriteLine(string.Empty); 375 | ssw.Reset(); 376 | } 377 | } 378 | 379 | private static int[] GetNumbersForAverage() 380 | { 381 | return new[] 382 | { 383 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 384 | 3, 4, 0, 385 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 386 | 12, 7, 8, 2, 387 | 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 388 | 0, 2, 12, 389 | 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 390 | 2, 3, 4, 391 | 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 392 | 12, 7, 8, 393 | 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 394 | 4, 0, 2, 395 | 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 396 | 7, 8, 2, 3, 397 | 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 398 | 2, 12, 7, 399 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 400 | 3, 4, 0, 401 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 402 | 12, 7, 8, 2, 403 | 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 404 | 0, 2, 12, 405 | 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 406 | 2, 3, 4, 407 | 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 408 | 12, 7, 8, 409 | 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 410 | 4, 0, 2, 411 | 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 412 | 7, 8, 2, 3, 413 | 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 414 | 2, 12, 7, 415 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 416 | 3, 4, 0, 417 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 418 | 12, 7, 8, 2, 419 | 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 420 | 0, 2, 12, 421 | 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 422 | 2, 3, 4, 423 | 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 424 | 12, 7, 8, 425 | 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 426 | 4, 0, 2, 427 | 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 428 | 7, 8, 2, 3, 429 | 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 430 | 2, 12, 7, 431 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 432 | 3, 4, 0, 433 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 434 | 12, 7, 8, 2, 435 | 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 436 | 0, 2, 12, 437 | 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 438 | 2, 3, 4, 439 | 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 440 | 12, 7, 8, 441 | 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 442 | 4, 0, 2, 443 | 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 444 | 7, 8, 2, 3, 445 | 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 446 | 2, 12, 7, 447 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 448 | 3, 4, 0, 449 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 450 | 12, 7, 8, 2, 451 | 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 452 | 0, 2, 12, 453 | 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 454 | 2, 3, 4, 455 | 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 456 | 12, 7, 8, 457 | 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 458 | 4, 0, 2, 459 | 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 460 | 7, 8, 2, 3, 461 | 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 462 | 2, 12, 7, 463 | 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 464 | 3, 4, 0, 465 | 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7, 8, 2, 3, 4, 0, 2, 12, 7 466 | }; 467 | } 468 | 469 | /// 470 | /// A callback function. 471 | /// 472 | private static void CallbackFunction() 473 | { 474 | Console.Out.WriteLine("callback reached."); 475 | } 476 | 477 | /// 478 | /// Calculates the average of given numbers. 479 | /// 480 | /// The numbers. 481 | /// 482 | private static double CalcAverage(int[] numbers) 483 | { 484 | var average = 0.0; 485 | 486 | if (numbers == null || numbers.Length == 0) 487 | { 488 | return 0.0; 489 | } 490 | 491 | foreach (var number in numbers) 492 | { 493 | average += number; 494 | } 495 | average /= numbers.Length; 496 | 497 | //Utils.ConsumeCpu(1, TimeSpan.FromSeconds(.01)); 498 | 499 | return average; 500 | } 501 | 502 | /// 503 | /// Writes to the console. 504 | /// 505 | /// The string. 506 | private static void WriteToConsole(string s) 507 | { 508 | Console.Out.WriteLine(s); 509 | } 510 | 511 | /// 512 | /// Performs a not-operation. 513 | /// 514 | /// 515 | /// if set to true [flag]. 516 | /// 517 | /// 518 | private static bool Not(bool flag) 519 | { 520 | return !flag; 521 | } 522 | } 523 | } -------------------------------------------------------------------------------- /NUnitTests/ThreadingThreadpoolTestObject.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | namespace ThreadPooling.NUnitTests 29 | { 30 | public class ThreadingThreadpoolTestObject 31 | { 32 | private readonly object lockObject = new object(); 33 | public int NumberOfCalls; 34 | 35 | public void Call() 36 | { 37 | lock (lockObject) 38 | { 39 | NumberOfCalls++; 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ThreadPool")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ThreadPool")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0b35efa3-16e0-4cd8-9414-def1af02346b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SingleThreadRunner.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System.Threading; 29 | 30 | namespace ThreadPooling 31 | { 32 | /// 33 | /// This is a frame for a single thread to run the defined payload. 34 | /// 35 | public class SingleThreadRunner 36 | { 37 | private bool signalClose; 38 | private bool signalWork; 39 | 40 | private WorkItem currentWorkItem; 41 | 42 | public ThreadPool ThreadPool { get; set; } 43 | public Thread Thread { get; set; } 44 | 45 | /// 46 | /// Initializes a new instance of the class. 47 | /// 48 | public SingleThreadRunner() 49 | { 50 | } 51 | 52 | /// 53 | /// Initializes a new instance of the class. 54 | /// 55 | /// The thread pool. 56 | public SingleThreadRunner(ThreadPool threadPool) 57 | { 58 | ThreadPool = threadPool; 59 | } 60 | 61 | /// 62 | /// Does the work reacting on and setting various signals. 63 | /// 64 | public void DoWork() 65 | { 66 | var spinWait = new SpinWait(); 67 | while (!signalClose) 68 | { 69 | if (signalWork) 70 | { 71 | while (currentWorkItem != null && !signalClose) 72 | { 73 | // Start the payload. 74 | currentWorkItem.Result = currentWorkItem.Delegate(currentWorkItem.DelegateInputParameters); 75 | 76 | // Set the work item to completed. 77 | currentWorkItem.IsCompleted = true; 78 | 79 | // Call the async callback - method, if available. 80 | if (currentWorkItem.AsyncCallback != null) 81 | { 82 | currentWorkItem.AsyncCallback.Invoke(); 83 | } 84 | 85 | // Dequeue the next work item. 86 | if (ThreadPool.IsDisposeDoneWorkItemsAutomatically) 87 | { 88 | // Return the work item automatically for reuse, if preferred. 89 | currentWorkItem = ThreadPool.DequeueWorkItemInternal(this, signalWork, currentWorkItem); 90 | } 91 | else 92 | { 93 | currentWorkItem = ThreadPool.DequeueWorkItemInternal(this, signalWork); 94 | } 95 | } 96 | // The worker has no more work or is paused. 97 | signalWork = false; 98 | } 99 | else 100 | { 101 | spinWait.SpinOnce(); 102 | } 103 | } 104 | // The thread is dead. 105 | signalClose = false; 106 | } 107 | 108 | /// 109 | /// Signals this instance to immediately start doing some work. 110 | /// 111 | public void SignalWork(WorkItem workItemToProcess) 112 | { 113 | // Wait for the main loop to be not busy before changing the current workItem. 114 | var spinWait = new SpinWait(); 115 | while (signalWork) 116 | { 117 | spinWait.SpinOnce(); 118 | Thread.MemoryBarrier(); 119 | } 120 | Interlocked.Exchange(ref currentWorkItem, workItemToProcess); 121 | signalWork = true; 122 | Thread.MemoryBarrier(); 123 | } 124 | 125 | /// 126 | /// Signals the workers to close. 127 | /// 128 | public void SignalShutDown() 129 | { 130 | signalClose = true; 131 | } 132 | 133 | /// 134 | /// Signals the workers to pause. 135 | /// 136 | public void SignalPause() 137 | { 138 | Thread.MemoryBarrier(); 139 | signalWork = false; 140 | Thread.MemoryBarrier(); 141 | } 142 | 143 | /// 144 | /// Signals the workers to resume. 145 | /// 146 | public void SignalResume() 147 | { 148 | Thread.MemoryBarrier(); 149 | signalWork = true; 150 | Thread.MemoryBarrier(); 151 | } 152 | 153 | /// 154 | /// Aborts this instance. 155 | /// 156 | public void Abort() 157 | { 158 | Thread.Abort(); 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /ThreadPool.ActionT.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System; 29 | using System.Threading; 30 | 31 | namespace ThreadPooling 32 | { 33 | public partial class ThreadPool 34 | { 35 | /// 36 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 37 | /// queued, to be executed. 38 | /// Information on the returned struct... 39 | /// 40 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 41 | /// has executed. 42 | /// 43 | /// 44 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 45 | /// avoid 46 | /// garbage-collector-cycles. 47 | /// 48 | /// 49 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 50 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 51 | /// internally thus returning almost instantly. 52 | /// 53 | /// 54 | /// The worker function. 55 | /// The async callback. 56 | /// 57 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 58 | /// 59 | public IWorkItemState EnqueueWorkItem(Action workerFunction, CallbackFunction asyncCallback = null) 60 | { 61 | var workItem = GetWorkItem(asyncCallback); 62 | workItem.DelegateInputParameters = new object[] {}; 63 | workItem.Delegate = delegateInputParameters => 64 | { 65 | workerFunction.Invoke(); 66 | return null; 67 | }; 68 | 69 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 70 | EnqueueWorkItemInternal(workItem); 71 | return workItemState; 72 | } 73 | 74 | /// 75 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 76 | /// queued, to be executed. 77 | /// Information on the returned struct... 78 | /// 79 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 80 | /// has executed. 81 | /// 82 | /// 83 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 84 | /// avoid 85 | /// garbage-collector-cycles. 86 | /// 87 | /// 88 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 89 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 90 | /// internally thus returning almost instantly. 91 | /// 92 | /// 93 | /// The type of the 1. 94 | /// The worker function. 95 | /// The arg1. 96 | /// The async callback. 97 | /// 98 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 99 | /// 100 | public IWorkItemState EnqueueWorkItem(Action workerFunction, T1 arg1, 101 | CallbackFunction asyncCallback = null) 102 | { 103 | var workItem = GetWorkItem(asyncCallback); 104 | workItem.DelegateInputParameters = new object[] {arg1}; 105 | workItem.Delegate = delegateInputParameters => 106 | { 107 | workerFunction.Invoke(arg1); 108 | return null; 109 | }; 110 | 111 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 112 | EnqueueWorkItemInternal(workItem); 113 | return workItemState; 114 | } 115 | 116 | /// 117 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 118 | /// queued, to be executed. 119 | /// Information on the returned struct... 120 | /// 121 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 122 | /// has executed. 123 | /// 124 | /// 125 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 126 | /// avoid 127 | /// garbage-collector-cycles. 128 | /// 129 | /// 130 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 131 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 132 | /// internally thus returning almost instantly. 133 | /// 134 | /// 135 | /// The type of the 1. 136 | /// The type of the 2. 137 | /// The worker function. 138 | /// The arg1. 139 | /// The arg2. 140 | /// The async callback. 141 | /// 142 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 143 | /// 144 | public IWorkItemState EnqueueWorkItem(Action workerFunction, T1 arg1, T2 arg2, 145 | CallbackFunction asyncCallback = null) 146 | { 147 | var workItem = GetWorkItem(asyncCallback); 148 | workItem.DelegateInputParameters = new object[] {arg1, arg2}; 149 | workItem.Delegate = delegateInputParameters => 150 | { 151 | workerFunction.Invoke(arg1, arg2); 152 | return null; 153 | }; 154 | 155 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 156 | EnqueueWorkItemInternal(workItem); 157 | return workItemState; 158 | } 159 | 160 | /// 161 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 162 | /// queued, to be executed. 163 | /// Information on the returned struct... 164 | /// 165 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 166 | /// has executed. 167 | /// 168 | /// 169 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 170 | /// avoid 171 | /// garbage-collector-cycles. 172 | /// 173 | /// 174 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 175 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 176 | /// internally thus returning almost instantly. 177 | /// 178 | /// 179 | /// The type of the 1. 180 | /// The type of the 2. 181 | /// The type of the 3. 182 | /// The worker function. 183 | /// The arg1. 184 | /// The arg2. 185 | /// The arg3. 186 | /// The async callback. 187 | /// 188 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 189 | /// 190 | public IWorkItemState EnqueueWorkItem(Action workerFunction, T1 arg1, T2 arg2, T3 arg3, 191 | CallbackFunction asyncCallback = null) 192 | { 193 | var workItem = GetWorkItem(asyncCallback); 194 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3}; 195 | workItem.Delegate = delegateInputParameters => 196 | { 197 | workerFunction.Invoke(arg1, arg2, arg3); 198 | return null; 199 | }; 200 | 201 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 202 | EnqueueWorkItemInternal(workItem); 203 | return workItemState; 204 | } 205 | 206 | /// 207 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 208 | /// queued, to be executed. 209 | /// Information on the returned struct... 210 | /// 211 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 212 | /// has executed. 213 | /// 214 | /// 215 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 216 | /// avoid 217 | /// garbage-collector-cycles. 218 | /// 219 | /// 220 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 221 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 222 | /// internally thus returning almost instantly. 223 | /// 224 | /// 225 | /// The type of the 1. 226 | /// The type of the 2. 227 | /// The type of the 3. 228 | /// The type of the 4. 229 | /// The worker function. 230 | /// The arg1. 231 | /// The arg2. 232 | /// The arg3. 233 | /// The arg4. 234 | /// The async callback. 235 | /// 236 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 237 | /// 238 | public IWorkItemState EnqueueWorkItem(Action workerFunction, T1 arg1, T2 arg2, 239 | T3 arg3, 240 | T4 arg4, CallbackFunction asyncCallback = null) 241 | { 242 | var workItem = GetWorkItem(asyncCallback); 243 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3, arg4}; 244 | workItem.Delegate = delegateInputParameters => 245 | { 246 | workerFunction.Invoke(arg1, arg2, arg3, arg4); 247 | return null; 248 | }; 249 | 250 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 251 | EnqueueWorkItemInternal(workItem); 252 | return workItemState; 253 | } 254 | 255 | /// 256 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 257 | /// queued, to be executed. 258 | /// Information on the returned struct... 259 | /// 260 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 261 | /// has executed. 262 | /// 263 | /// 264 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 265 | /// avoid 266 | /// garbage-collector-cycles. 267 | /// 268 | /// 269 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 270 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 271 | /// internally thus returning almost instantly. 272 | /// 273 | /// 274 | /// The type of the 1. 275 | /// The type of the 2. 276 | /// The type of the 3. 277 | /// The type of the 4. 278 | /// The type of the 5. 279 | /// The worker function. 280 | /// The arg1. 281 | /// The arg2. 282 | /// The arg3. 283 | /// The arg4. 284 | /// The arg5. 285 | /// The async callback. 286 | /// 287 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 288 | /// 289 | public IWorkItemState EnqueueWorkItem(Action workerFunction, T1 arg1, 290 | T2 arg2, 291 | T3 arg3, T4 arg4, T5 arg5, CallbackFunction asyncCallback = null) 292 | { 293 | var workItem = GetWorkItem(asyncCallback); 294 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3, arg4, arg5}; 295 | workItem.Delegate = delegateInputParameters => 296 | { 297 | workerFunction.Invoke(arg1, arg2, arg3, arg4, arg5); 298 | return null; 299 | }; 300 | 301 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 302 | EnqueueWorkItemInternal(workItem); 303 | return workItemState; 304 | } 305 | } 306 | } -------------------------------------------------------------------------------- /ThreadPool.FuncT.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System; 29 | 30 | namespace ThreadPooling 31 | { 32 | public partial class ThreadPool 33 | { 34 | /// 35 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 36 | /// queued, to be executed. 37 | /// Information on the returned struct... 38 | /// 39 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 40 | /// has executed. 41 | /// 42 | /// 43 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 44 | /// avoid 45 | /// garbage-collector-cycles. 46 | /// 47 | /// 48 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 49 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 50 | /// ManualResetEvent internally thus returning almost instantly. 51 | /// 52 | /// 53 | /// The type of the result. 54 | /// The worker function. 55 | /// The async callback. 56 | /// 57 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 58 | /// 59 | public IWorkItemState EnqueueWorkItem(Func workerFunction, CallbackFunction asyncCallback = null) 60 | { 61 | var workItem = GetWorkItem(asyncCallback); 62 | workItem.DelegateInputParameters = new object[] {}; 63 | workItem.Delegate = delegateInputParameters => { return workerFunction.Invoke(); }; 64 | 65 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 66 | EnqueueWorkItemInternal(workItem); 67 | return workItemState; 68 | } 69 | 70 | /// 71 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 72 | /// queued, to be executed. 73 | /// Information on the returned struct... 74 | /// 75 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 76 | /// has executed. 77 | /// 78 | /// 79 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 80 | /// avoid 81 | /// garbage-collector-cycles. 82 | /// 83 | /// 84 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 85 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 86 | /// ManualResetEvent internally thus returning almost instantly. 87 | /// 88 | /// 89 | /// The type of the 1. 90 | /// The type of the result. 91 | /// The worker function. 92 | /// The arg1. 93 | /// The async callback. 94 | /// 95 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 96 | /// 97 | public IWorkItemState EnqueueWorkItem(Func workerFunction, T1 arg1, 98 | CallbackFunction asyncCallback = null) 99 | { 100 | var workItem = GetWorkItem(asyncCallback); 101 | 102 | workItem.DelegateInputParameters = new object[] {arg1}; 103 | workItem.Delegate = delegateInputParameters => workerFunction.Invoke(arg1); 104 | 105 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 106 | EnqueueWorkItemInternal(workItem); 107 | return workItemState; 108 | } 109 | 110 | /// 111 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 112 | /// queued, to be executed. 113 | /// Information on the returned struct... 114 | /// 115 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 116 | /// has executed. 117 | /// 118 | /// 119 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 120 | /// avoid 121 | /// garbage-collector-cycles. 122 | /// 123 | /// 124 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 125 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 126 | /// ManualResetEvent internally thus returning almost instantly. 127 | /// 128 | /// 129 | /// The type of the 1. 130 | /// The type of the 2. 131 | /// The type of the result. 132 | /// The worker function. 133 | /// The arg1. 134 | /// The arg2. 135 | /// The async callback. 136 | /// 137 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 138 | /// 139 | public IWorkItemState EnqueueWorkItem(Func workerFunction, T1 arg1, T2 arg2, 140 | CallbackFunction asyncCallback = null) 141 | { 142 | var workItem = GetWorkItem(asyncCallback); 143 | workItem.DelegateInputParameters = new object[] {arg1, arg2}; 144 | workItem.Delegate = delegateInputParameters => workerFunction.Invoke(arg1, arg2); 145 | 146 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 147 | EnqueueWorkItemInternal(workItem); 148 | return workItemState; 149 | } 150 | 151 | /// 152 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 153 | /// queued, to be executed. 154 | /// Information on the returned struct... 155 | /// 156 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 157 | /// has executed. 158 | /// 159 | /// 160 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 161 | /// avoid 162 | /// garbage-collector-cycles. 163 | /// 164 | /// 165 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 166 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 167 | /// ManualResetEvent internally thus returning almost instantly. 168 | /// 169 | /// 170 | /// The type of the 1. 171 | /// The type of the 2. 172 | /// The type of the 3. 173 | /// The type of the result. 174 | /// The worker function. 175 | /// The arg1. 176 | /// The arg2. 177 | /// The arg3. 178 | /// The async callback. 179 | /// 180 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 181 | /// 182 | public IWorkItemState EnqueueWorkItem(Func workerFunction, T1 arg1, T2 arg2, 183 | T3 arg3, 184 | CallbackFunction asyncCallback = null) 185 | { 186 | var workItem = GetWorkItem(asyncCallback); 187 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3}; 188 | workItem.Delegate = delegateInputParameters => workerFunction.Invoke(arg1, arg2, arg3); 189 | 190 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 191 | EnqueueWorkItemInternal(workItem); 192 | return workItemState; 193 | } 194 | 195 | /// 196 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 197 | /// queued, to be executed. 198 | /// Information on the returned struct... 199 | /// 200 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 201 | /// has executed. 202 | /// 203 | /// 204 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 205 | /// avoid 206 | /// garbage-collector-cycles. 207 | /// 208 | /// 209 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 210 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 211 | /// ManualResetEvent internally thus returning almost instantly. 212 | /// 213 | /// 214 | /// The type of the 1. 215 | /// The type of the 2. 216 | /// The type of the 3. 217 | /// The type of the 4. 218 | /// The type of the result. 219 | /// The worker function. 220 | /// The arg1. 221 | /// The arg2. 222 | /// The arg3. 223 | /// The arg4. 224 | /// The async callback. 225 | /// 226 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 227 | /// 228 | public IWorkItemState EnqueueWorkItem(Func workerFunction, T1 arg1, 229 | T2 arg2, 230 | T3 arg3, T4 arg4, CallbackFunction asyncCallback = null) 231 | { 232 | var workItem = GetWorkItem(asyncCallback); 233 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3, arg4}; 234 | workItem.Delegate = delegateInputParameters => workerFunction.Invoke(arg1, arg2, arg3, arg4); 235 | 236 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 237 | EnqueueWorkItemInternal(workItem); 238 | return workItemState; 239 | } 240 | 241 | /// 242 | /// Enqueues the work item. Returns a work-item-state-struct as a handle to the operation that is just about, or 243 | /// queued, to be executed. 244 | /// Information on the returned struct... 245 | /// 246 | /// Call the result property on this struct to trigger a lock, thus blocking your current thread until the function 247 | /// has executed. 248 | /// 249 | /// 250 | /// Call Dispose on that returned item to automatically reuse the data-structure behind each work-item in order to 251 | /// avoid 252 | /// garbage-collector-cycles. 253 | /// 254 | /// 255 | /// Use its IsCompleted-Property to verify within a monitor if your method has finished executing. The 256 | /// IsCompleted-Property actually triggers a WaitOne(1) on a 257 | /// ManualResetEvent internally thus returning almost instantly. 258 | /// 259 | /// 260 | /// The type of the 1. 261 | /// The type of the 2. 262 | /// The type of the 3. 263 | /// The type of the 4. 264 | /// The type of the 5. 265 | /// The type of the result. 266 | /// The worker function. 267 | /// The arg1. 268 | /// The arg2. 269 | /// The arg3. 270 | /// The arg4. 271 | /// The arg5. 272 | /// The async callback. 273 | /// 274 | /// Returns a work-item-state-struct as a handle to the operation that is just about, or queued, to be executed. 275 | /// 276 | public IWorkItemState EnqueueWorkItem(Func workerFunction, 277 | T1 arg1, 278 | T2 arg2, T3 arg3, T4 arg4, T5 arg5, CallbackFunction asyncCallback = null) 279 | { 280 | var workItem = GetWorkItem(asyncCallback); 281 | workItem.DelegateInputParameters = new object[] {arg1, arg2, arg3, arg4, arg5}; 282 | workItem.Delegate = delegateInputParameters => workerFunction.Invoke(arg1, arg2, arg3, arg4, arg5); 283 | 284 | var workItemState = new WorkItemState(workItem.WorkItemStateTypeless); 285 | EnqueueWorkItemInternal(workItem); 286 | return workItemState; 287 | } 288 | } 289 | } -------------------------------------------------------------------------------- /ThreadPool.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System.Collections.Concurrent; 29 | using System.Collections.Generic; 30 | using System.Threading; 31 | 32 | namespace ThreadPooling 33 | { 34 | /// 35 | /// This class implements a thread-pool. It buffers all the work items, which regrettably have to be classes, and 36 | /// reuses them. It only cleans them up at 37 | /// shutdown. 38 | /// 39 | public partial class ThreadPool 40 | { 41 | /// 42 | /// The form of the callback delegate that carries the payload of the workItem. 43 | /// 44 | internal delegate object WorkItemCallback(object state); 45 | 46 | /// 47 | /// The callback function that should be called when the work item is finished. 48 | /// 49 | public delegate void CallbackFunction(); 50 | 51 | private bool isDisposeDoneWorkItemsAutomatically; 52 | private readonly Queue threads; 53 | private readonly ConcurrentQueue threadsIdle; 54 | private int threadsWorking; 55 | private readonly ConcurrentQueue workItemQueue = new ConcurrentQueue(); 56 | 57 | private readonly ConcurrentQueue returnedWorkItems = new ConcurrentQueue(); 58 | private bool shutDownSignaled; 59 | private readonly object lockObjectShutDownSignaled = new object(); 60 | 61 | public int NumberOfThreads { get; } 62 | 63 | /// 64 | /// Gets or sets a value indicating whether this instance is set to dispose done work items automatically. Beware: If 65 | /// you enable this option, the 66 | /// dispose method of each work item is called immediately after its completion, thus destroying the reference. This 67 | /// obviously is only an viable option 68 | /// when using the action-interface (no return values) together with the WaitForEveryWorkerIdle-Method. 69 | /// 70 | /// 71 | /// true if this instance is dispose done work items automatically; otherwise, false. 72 | /// 73 | public bool IsDisposeDoneWorkItemsAutomatically 74 | { 75 | get 76 | { 77 | Thread.MemoryBarrier(); 78 | return isDisposeDoneWorkItemsAutomatically; 79 | } 80 | set 81 | { 82 | isDisposeDoneWorkItemsAutomatically = value; 83 | Thread.MemoryBarrier(); 84 | } 85 | } 86 | 87 | /// 88 | /// Initializes a new instance of the class. 89 | /// 90 | public ThreadPool(int numberOfThreads, string threadsNamePrefix) 91 | { 92 | NumberOfThreads = numberOfThreads; 93 | threads = new Queue(); 94 | threadsIdle = new ConcurrentQueue(); 95 | 96 | // allocate threads... 97 | for (var i = 0; i < NumberOfThreads; i++) 98 | { 99 | var singleThreadRunner = new SingleThreadRunner(this); 100 | singleThreadRunner.Thread = new Thread(singleThreadRunner.DoWork); 101 | singleThreadRunner.Thread.Name = threadsNamePrefix + (i + 1); 102 | singleThreadRunner.Thread.IsBackground = true; 103 | 104 | threads.Enqueue(singleThreadRunner); 105 | threadsIdle.Enqueue(singleThreadRunner); 106 | 107 | singleThreadRunner.Thread.Start(); 108 | } 109 | } 110 | 111 | /// 112 | /// Clears the work item queue. 113 | /// 114 | public void ClearWorkItemQueue() 115 | { 116 | WorkItem wi; 117 | while (workItemQueue.TryDequeue(out wi)) 118 | {} 119 | } 120 | 121 | /// 122 | /// The number of items that are still to be processed. 123 | /// 124 | /// 125 | public int NumberOfItemsLeft() 126 | { 127 | Thread.MemoryBarrier(); 128 | return workItemQueue.Count; 129 | } 130 | 131 | /// 132 | /// The number of items that are done processing and returned. 133 | /// 134 | /// 135 | public int NumberOfItemsDone() 136 | { 137 | Thread.MemoryBarrier(); 138 | return returnedWorkItems.Count; 139 | } 140 | 141 | /// 142 | /// Enqueues the work item. 143 | /// 144 | /// The work item. 145 | internal void EnqueueWorkItemInternal(WorkItem workItem) 146 | { 147 | // look for an idle worker... 148 | SingleThreadRunner singleThreadRunner; 149 | if (threadsIdle.TryDequeue(out singleThreadRunner)) 150 | { 151 | // hand over the work item... 152 | workItem.SingleThreadRunner = singleThreadRunner; 153 | Interlocked.Increment(ref threadsWorking); 154 | singleThreadRunner.SignalWork(workItem); 155 | } 156 | else 157 | { 158 | // just enqueue the item since all workers are busy... 159 | workItemQueue.Enqueue(workItem); 160 | } 161 | } 162 | 163 | /// 164 | /// Dequeues the work item. 165 | /// 166 | /// The single thread runner. 167 | /// 168 | /// if set to true [is get new one]. 169 | /// 170 | /// The returned work item. 171 | /// 172 | /// , if a work item has been 173 | /// successfully dequeued. otherwise. 174 | /// 175 | internal WorkItem DequeueWorkItemInternal(SingleThreadRunner singleThreadRunner, bool isGetNewOne, 176 | WorkItem returnedWorkItem = null) 177 | { 178 | if (returnedWorkItem != null) 179 | { 180 | returnedWorkItems.Enqueue(returnedWorkItem); 181 | } 182 | 183 | if (!shutDownSignaled && isGetNewOne) 184 | { 185 | WorkItem workItem; 186 | if (workItemQueue.TryDequeue(out workItem)) 187 | { 188 | workItem.SingleThreadRunner = singleThreadRunner; 189 | return workItem; 190 | } 191 | } 192 | 193 | // If we are here, there is no more work to do left... 194 | // The worker has to be set to idle... 195 | Interlocked.Decrement(ref threadsWorking); 196 | threadsIdle.Enqueue(singleThreadRunner); 197 | return null; 198 | } 199 | 200 | private WorkItem GetWorkItem(CallbackFunction asyncCallback) 201 | { 202 | WorkItem workItem; 203 | if (!returnedWorkItems.TryDequeue(out workItem)) 204 | { 205 | workItem = new WorkItem(); 206 | workItem.WorkItemStateTypeless = new WorkItemStateTypeless(workItem); 207 | } 208 | 209 | workItem.SingleThreadRunner = null; 210 | workItem.IsCompleted = false; 211 | workItem.Result = null; 212 | workItem.AsyncCallback = asyncCallback; 213 | return workItem; 214 | } 215 | 216 | /// 217 | /// Returns the work item. 218 | /// 219 | /// The returned work item. 220 | public void ReturnWorkItem(WorkItem returnedWorkItem) 221 | { 222 | returnedWorkItems.Enqueue(returnedWorkItem); 223 | } 224 | 225 | /// 226 | /// Waits for the queue to empty. 227 | /// 228 | public void WaitForEveryWorkerIdle() 229 | { 230 | // A spinWait ensures a yield from time to time, forcing the CPU to do a context switch, thus allowing other processes to finish. 231 | var spinWait = new SpinWait(); 232 | while (threadsWorking > 0) 233 | { 234 | Thread.MemoryBarrier(); 235 | spinWait.SpinOnce(); 236 | } 237 | } 238 | 239 | /// 240 | /// Clears the work item cache of all returned and "to be reused" work items returned via the dispose-method of a 241 | /// work-item-state-struct. 242 | /// 243 | public void ClearWorkItemCache() 244 | { 245 | WorkItem w; 246 | while(returnedWorkItems.TryDequeue(out w)) 247 | {} 248 | } 249 | 250 | /// 251 | /// Aborts all active threads. 252 | /// 253 | public void ShutDown() 254 | { 255 | // First, we want to close. So stop dealing new work items... 256 | lock (lockObjectShutDownSignaled) 257 | { 258 | shutDownSignaled = true; 259 | } 260 | 261 | // signal the shutdown-command to all workers... 262 | if (threads.Count > 0) 263 | { 264 | foreach (var thread in threads) 265 | { 266 | thread.SignalShutDown(); 267 | } 268 | } 269 | } 270 | 271 | /// 272 | /// Pauses all active threads. 273 | /// 274 | public void Sleep() 275 | { 276 | // signal the pause-command to all workers... 277 | if (threads.Count > 0) 278 | { 279 | foreach (var thread in threads) 280 | { 281 | thread.SignalPause(); 282 | } 283 | } 284 | } 285 | 286 | /// 287 | /// Resumes all active threads. 288 | /// 289 | public void Wakeup() 290 | { 291 | // signal the resume-command to all workers... 292 | if (threads.Count > 0) 293 | { 294 | foreach (var thread in threads) 295 | { 296 | thread.SignalResume(); 297 | } 298 | } 299 | } 300 | } 301 | } -------------------------------------------------------------------------------- /ThreadPooling.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3F9CAEDA-D8A2-4253-A44F-C8226C36EB5B} 8 | Library 9 | Properties 10 | ThreadPooling 11 | ThreadPooling 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | False 35 | lib\nunit.framework.dll 36 | 37 | 38 | False 39 | lib\SplitStopWatch.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /ThreadPooling.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | *************************************************************************** 3 | This is free and unencumbered software released into the public domain. 4 | 5 | Anyone is free to copy, modify, publish, use, compile, sell, or 6 | distribute this software, either in source code form or as a compiled 7 | binary, for any purpose, commercial or non-commercial, and by any 8 | means. 9 | 10 | In jurisdictions that recognize copyright laws, the author or authors 11 | of this software dedicate any and all copyright interest in the 12 | software to the public domain. We make this dedication for the benefit 13 | of the public at large and to the detriment of our heirs and 14 | successors. We intend this dedication to be an overt act of 15 | relinquishment in perpetuity of all present and future rights to this 16 | software under copyright law. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | For more information, please refer to <http://unlicense.org> 27 | *************************************************************************** -------------------------------------------------------------------------------- /WorkItem.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | using System.Threading; 29 | 30 | namespace ThreadPooling 31 | { 32 | /// 33 | /// This is a wrapper-class for a work item. 34 | /// 35 | public class WorkItem 36 | { 37 | private object result; 38 | 39 | public bool IsCompleted { get; set; } 40 | internal ThreadPool.WorkItemCallback Delegate { get; set; } 41 | public object DelegateInputParameters { get; set; } 42 | public WorkItemStateTypeless WorkItemStateTypeless { get; set; } 43 | public SingleThreadRunner SingleThreadRunner { get; set; } 44 | 45 | /// 46 | /// Gets or sets the result. 47 | /// 48 | /// The result. 49 | public object Result 50 | { 51 | get 52 | { 53 | // SpinWait for the workItem to finish. 54 | var spinWait = new SpinWait(); 55 | while (!IsCompleted) 56 | { 57 | spinWait.SpinOnce(); 58 | Thread.MemoryBarrier(); 59 | } 60 | return result; 61 | } 62 | set { result = value; } 63 | } 64 | 65 | /// 66 | /// Initializes a new instance of the class. 67 | /// 68 | internal WorkItem() 69 | { 70 | } 71 | 72 | /// 73 | /// Initializes a new instance of the class. 74 | /// 75 | internal WorkItem(ThreadPool.WorkItemCallback functionDelegate, object delegateInputParameters) 76 | { 77 | Delegate = functionDelegate; 78 | DelegateInputParameters = delegateInputParameters; 79 | WorkItemStateTypeless = new WorkItemStateTypeless(this); 80 | } 81 | 82 | /// 83 | /// Gets or sets the async callback. 84 | /// 85 | /// The async callback. 86 | public ThreadPool.CallbackFunction AsyncCallback { get; set; } 87 | } 88 | } -------------------------------------------------------------------------------- /WorkItemState.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | namespace ThreadPooling 29 | { 30 | /// 31 | /// This is an implementation of the IWorkItemStateTypeless interface. 32 | /// 33 | /// The type of the result. 34 | public struct WorkItemState : IWorkItemState 35 | { 36 | private bool disposed; 37 | private readonly WorkItemStateTypeless workItemStateTypeless; 38 | 39 | /// 40 | /// Gets a value indicating whether this instance is completed gracefully. 41 | /// 42 | /// 43 | /// true if this instance is completed gracefully; otherwise, false. 44 | /// 45 | public bool IsStopped => workItemStateTypeless.IsStopped; 46 | 47 | /// 48 | /// Gets or sets the result. 49 | /// 50 | /// The result. 51 | public T Result => (T) workItemStateTypeless.Result; 52 | 53 | /// 54 | /// Initializes a new instance of the class. 55 | /// 56 | /// State of the work item. 57 | public WorkItemState(WorkItemStateTypeless workItemStateTypeless) 58 | { 59 | this.workItemStateTypeless = workItemStateTypeless; 60 | disposed = false; 61 | } 62 | 63 | /// 64 | /// Releases unmanaged and - optionally - managed resources 65 | /// 66 | /// 67 | /// true to release both managed and 68 | /// unmanaged resources; false to release only unmanaged 69 | /// resources. 70 | /// 71 | public void Dispose(bool disposing) 72 | { 73 | if (!disposed) 74 | { 75 | if (disposing) 76 | { 77 | workItemStateTypeless.WorkItem.SingleThreadRunner.ThreadPool.ReturnWorkItem( 78 | workItemStateTypeless.WorkItem); 79 | } 80 | disposed = true; 81 | } 82 | } 83 | 84 | /// 85 | /// Performs application-defined tasks associated with freeing, 86 | /// releasing, or resetting unmanaged resources. 87 | /// 88 | public void Dispose() 89 | { 90 | Dispose(true); 91 | } 92 | } 93 | 94 | /// 95 | /// This is an implementation of the IWorkItemStateTypeless interface. 96 | /// 97 | public struct WorkItemState : IWorkItemState 98 | { 99 | private bool disposed; 100 | private readonly WorkItemStateTypeless workItemStateTypeless; 101 | 102 | /// 103 | /// Gets a value indicating whether this instance is completed gracefully. 104 | /// 105 | /// 106 | /// true if this instance is completed gracefully; otherwise, false. 107 | /// 108 | public bool IsStopped => workItemStateTypeless.IsStopped; 109 | 110 | /// 111 | /// Initializes a new instance of the class. 112 | /// 113 | /// State of the work item. 114 | public WorkItemState(WorkItemStateTypeless workItemStateTypeless) 115 | { 116 | this.workItemStateTypeless = workItemStateTypeless; 117 | disposed = false; 118 | } 119 | 120 | /// 121 | /// Is a blocking operation. 122 | /// Waits for the work item to finish. 123 | /// 124 | /// The result. 125 | public void Result() 126 | { 127 | #pragma warning disable 168 128 | var o = workItemStateTypeless.Result; 129 | #pragma warning restore 168 130 | } 131 | 132 | /// 133 | /// Releases unmanaged and - optionally - managed resources 134 | /// 135 | /// 136 | /// true to release both managed and 137 | /// unmanaged resources; false to release only unmanaged 138 | /// resources. 139 | /// 140 | public void Dispose(bool disposing) 141 | { 142 | if (!disposed) 143 | { 144 | if (disposing) 145 | { 146 | workItemStateTypeless.WorkItem.SingleThreadRunner.ThreadPool.ReturnWorkItem( 147 | workItemStateTypeless.WorkItem); 148 | } 149 | disposed = true; 150 | } 151 | } 152 | 153 | /// 154 | /// Performs application-defined tasks associated with freeing, 155 | /// releasing, or resetting unmanaged resources. 156 | /// 157 | public void Dispose() 158 | { 159 | Dispose(true); 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /WorkItemStateTypeless.cs: -------------------------------------------------------------------------------- 1 | // *************************************************************************** 2 | // This is free and unencumbered software released into the public domain. 3 | // 4 | // Anyone is free to copy, modify, publish, use, compile, sell, or 5 | // distribute this software, either in source code form or as a compiled 6 | // binary, for any purpose, commercial or non-commercial, and by any 7 | // means. 8 | // 9 | // In jurisdictions that recognize copyright laws, the author or authors 10 | // of this software dedicate any and all copyright interest in the 11 | // software to the public domain. We make this dedication for the benefit 12 | // of the public at large and to the detriment of our heirs and 13 | // successors. We intend this dedication to be an overt act of 14 | // relinquishment in perpetuity of all present and future rights to this 15 | // software under copyright law. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | // OTHER DEALINGS IN THE SOFTWARE. 24 | // 25 | // For more information, please refer to 26 | // *************************************************************************** 27 | 28 | namespace ThreadPooling 29 | { 30 | /// 31 | /// The state and the remote control for a work item. 32 | /// 33 | public class WorkItemStateTypeless : IWorkItemStateTypeless 34 | { 35 | public WorkItem WorkItem { get; set; } 36 | 37 | /// 38 | /// Gets a value indicating whether this instance is completed gracefully. 39 | /// 40 | /// 41 | /// true if this instance is completed gracefully; otherwise, false. 42 | /// 43 | public bool IsStopped => WorkItem.IsCompleted; 44 | 45 | /// 46 | /// Gets the result. 47 | /// 48 | /// The result. 49 | public object Result => WorkItem.Result; 50 | 51 | /// 52 | /// Initializes a new instance of the class. 53 | /// 54 | /// The work item. 55 | public WorkItemStateTypeless(WorkItem workItem) 56 | { 57 | WorkItem = workItem; 58 | } 59 | 60 | /// 61 | /// Performs application-defined tasks associated with freeing, 62 | /// releasing, or resetting unmanaged resources. 63 | /// 64 | public void Dispose() 65 | { 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /bin/Release/LockFreeQueue.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/bin/Release/LockFreeQueue.dll -------------------------------------------------------------------------------- /bin/Release/SplitStopWatch.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/bin/Release/SplitStopWatch.dll -------------------------------------------------------------------------------- /bin/Release/ThreadPooling.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/bin/Release/ThreadPooling.dll -------------------------------------------------------------------------------- /bin/Release/Utilities.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/bin/Release/Utilities.dll -------------------------------------------------------------------------------- /bin/Release/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/bin/Release/nunit.framework.dll -------------------------------------------------------------------------------- /lib/SplitStopWatch.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/lib/SplitStopWatch.dll -------------------------------------------------------------------------------- /lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnterrainerInformatik/threadpool/3a45379b7b46cac0c2cbb5fc09b0ca44a96aa975/lib/nunit.framework.dll -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ``` 2 | /************************************************************************** 3 | * 4 | * by Unterrainer Informatik OG. 5 | * This is free and unencumbered software released into the public domain. 6 | * Anyone is free to copy, modify, publish, use, compile, sell, or 7 | * distribute this software, either in source code form or as a compiled 8 | * binary, for any purpose, commercial or non-commercial, and by any 9 | * means. 10 | * 11 | * In jurisdictions that recognize copyright laws, the author or authors 12 | * of this software dedicate any and all copyright interest in the 13 | * software to the public domain. We make this dedication for the benefit 14 | * of the public at large and to the detriment of our heirs and 15 | * successors. We intend this dedication to be an overt act of 16 | * relinquishment in perpetuity of all present and future rights to this 17 | * software under copyright law. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * For more information, please refer to 28 | * 29 | * (In other words you may copy, use, change, redistribute and sell it without 30 | * any restrictions except for not suing me because it broke something.) 31 | * 32 | ***************************************************************************/ 33 | 34 | ``` 35 | 36 | # General 37 | 38 | This section contains various useful projects that should help your development-process. 39 | 40 | This section of our GIT repositories is free. You may copy, use or rewrite every single one of its contained projects to your hearts content. 41 | In order to get help with basic GIT commands you may try [the GIT cheat-sheet][coding] on our [homepage][homepage]. 42 | 43 | This repository located on our [homepage][homepage] is private since this is the master- and release-branch. You may clone it, but it will be read-only. 44 | If you want to contribute to our repository (push, open pull requests), please use the copy on github located here: [the public github repository][github] 45 | 46 | # ThreadPool 47 | 48 | This class implements a thread-pool. 49 | It buffers all the work items, which regrettably have to be classes, and reuses them. It only cleans them up at shutdown. 50 | 51 | The reason we wrote this although there is the Parallels library is because unlike with that library you can enqueue different workers in a single thread-pool. It takes every function that is wrapped as a workload regardless of how many parameters or return-values it has. You can mix them all together and start the pool. 52 | 53 | You may wait for the whole pool to finis (join) or on every single work-item. 54 | 55 | #### Example 56 | 57 | ```csharp 58 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 59 | 60 | List> wirs = new List>(); 61 | 62 | for (int i = 0; i < 50; i++) 63 | { 64 | IWorkItemState wir = threadPool.EnqueueWorkItem(new Func(Not), true); 65 | wirs.Add(wir); 66 | } 67 | 68 | threadPool.WaitForEveryWorkerIdle(); 69 | threadPool.ShutDown(); 70 | ``` 71 | 72 | You may as well pause and resume whenever you please. 73 | 74 | ```csharp 75 | threadPool = new ThreadPool(Environment.ProcessorCount, "testWorker"); 76 | 77 | List wirs = new List(); 78 | 79 | for (int i = 0; i < 10; i++) 80 | { 81 | if (i == 5) 82 | { 83 | threadPool.Sleep(); 84 | Thread.Sleep(2000); 85 | } 86 | IWorkItemState wir = threadPool.EnqueueWorkItem(WriteToConsole, "test " + (i + 1)); 87 | wirs.Add(wir); 88 | } 89 | 90 | threadPool.Wakeup(); 91 | 92 | foreach (IWorkItemState workItemState in wirs) 93 | { 94 | workItemState.Result(); 95 | workItemState.Dispose(); 96 | } 97 | 98 | threadPool.ShutDown(); 99 | ``` 100 | 101 | Take a look at the included unit-tests for further guidance. 102 | 103 | [homepage]: http://www.unterrainer.info 104 | [coding]: http://www.unterrainer.info/Home/Coding 105 | [github]: https://github.com/UnterrainerInformatik/threadpool --------------------------------------------------------------------------------