Proof of concept on how to queue items and execute them. Watch for memory leaks in this POC the GC has been tested and appears to work.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 73 74 75 76 77 78 79 80 81 82 83 84 85 |
Imports System.Runtime.InteropServices Imports System.Threading Imports System.Windows.Forms.VisualStyles Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub Private tasks As New Queue(Of Action) Private Sub SomeWork() System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " Starting work") Threading.Thread.Sleep(200) System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " Work completed") End Sub Private RunningThread As Integer Private Lock As New Object Private tasksWithParams As New Queue(Of Task(Of Object)) Private Function SomeWorkWithParams(ByVal id As Object, ByRef o As Object) As Object Dim MyDict As Dictionary(Of String, String) = id 'System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " SomeWorkWithParams Starting work on item - " & id & "-" & MyDict.First.Value) 'Threading.Thread.Sleep(2) 'System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " SomeWorkWithParams Work completed - " & id & "-" & MyDict.First.Value) Callback() 'o = Nothing Return False End Function Dim GCInterval As Integer = 0 Private Sub Callback() If GCInterval Mod 1000 = 0 Then System.Diagnostics.Debug.WriteLine("Cleaning up garbage mod 100") GC.Collect() End If GCInterval += 1 'If tasks.Count > 0 Then If tasksWithParams.Count > 0 Then 'Dim Task As Action Dim t As Task SyncLock (Lock) 'Task = tasks.Dequeue System.Diagnostics.Debug.WriteLine(tasksWithParams.Count & " left in queue") t = tasksWithParams.Dequeue t.Start() End SyncLock 'Task.BeginInvoke(AddressOf Callback, Nothing) Else Threading.Interlocked.Decrement(RunningThread) System.Diagnostics.Debug.WriteLine("Cleaning up garbage queue finished") GC.Collect() End If End Sub Private Function AddItemTOQueue(t As Task(Of Object), ByVal I As Object, ByVal o As Object) 'Dim Task As New Action(AddressOf SomeWork) If RunningThread < 1 Then 'Task.BeginInvoke(AddressOf Callback, MyArgument) t.Start() Threading.Interlocked.Increment(RunningThread) Else SyncLock (Lock) 'tasks.Enqueue(Task) tasksWithParams.Enqueue(t) End SyncLock End If Return True End Function Dim Ii As Integer = 0 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim MyArgument As New Dictionary(Of String, String) For i = 0 To 4999 Ii += 1 MyArgument = New Dictionary(Of String, String) MyArgument.Add("Test" & Ii, "test" & Ii) Dim t As Task(Of Object) = New Threading.Tasks.Task(Of Object)(Function() SomeWorkWithParams(MyArgument, 3)) AddItemTOQueue(t, 5, 7) 'MyArgument = Nothing Next End Sub End Class |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CSharpQueue { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Dictionary<string, string> MyArgument = new Dictionary<string, string>(); for (var i = 0; i <= 4999; i++) { Ii += 1; MyArgument = new Dictionary<string, string>(); MyArgument.Add("Test" + Ii, "test" + Ii); object Myval = 3; Task<bool> t = new System.Threading.Tasks.Task<bool>(() => Convert.ToBoolean(SomeWorkWithParams(MyArgument, ref Myval))); AddItemTOQueue(t, 5, 7); } } private Queue<Action> tasks = new Queue<Action>(); private void SomeWork() { System.Diagnostics.Debug.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " Starting work"); System.Threading.Thread.Sleep(200); System.Diagnostics.Debug.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " Work completed"); } private int RunningThread; private object Lock = new object(); private Queue<Task<bool>> tasksWithParams = new Queue<Task<bool>>(); private object SomeWorkWithParams(object id, ref object o) { Dictionary<string, string> MyDict = (Dictionary<string, string>)id; // System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " SomeWorkWithParams Starting work on item - " & id & "-" & MyDict.First.Value) // Threading.Thread.Sleep(2) // System.Diagnostics.Debug.WriteLine(Threading.Thread.CurrentThread.ManagedThreadId & " SomeWorkWithParams Work completed - " & id & "-" & MyDict.First.Value) Callback(); // o = Nothing return Convert.ToBoolean(new Random().Next(0, 2)); } private int GCInterval = 0; private void Callback() { if (GCInterval % 1000 == 0) { System.Diagnostics.Debug.WriteLine("Cleaning up garbage mod 100"); GC.Collect(); } GCInterval += 1; // If tasks.Count > 0 Then if (tasksWithParams.Count > 0) { // Dim Task As Action Task<bool> t; lock ((Lock)) { // Task = tasks.Dequeue System.Diagnostics.Debug.WriteLine(tasksWithParams.Count + " left in queue"); t = tasksWithParams.Dequeue(); t.Start(); } } else { System.Threading.Interlocked.Decrement(ref RunningThread); System.Diagnostics.Debug.WriteLine("Cleaning up garbage queue finished"); GC.Collect(); } } private bool AddItemTOQueue(Task<bool> t, object I, object o) { // Dim Task As New Action(AddressOf SomeWork) if (RunningThread < 1) { // Task.BeginInvoke(AddressOf Callback, MyArgument) t.Start(); System.Threading.Interlocked.Increment(ref RunningThread); } else lock ((Lock)) // tasks.Enqueue(Task) tasksWithParams.Enqueue(t); return true; } private int Ii = 0; } } |