1

I have code that does around 20 calculations on a DataTable. Instead of doing the calculations one-by-one, I was hoping to expedite the process by having a separate thread for each calculation. The below code is a simplified analog of what I am actually doing, but it should be enough to help me along.

I found the following sites and posts that were similar, but I was still unable to extrapolate to my situation—I apologize for my idiocy.

  1. Multi Threading with Return value : vb.net
  2. MSDN: BackgroundWorker Class
  3. Multithreading calculations with state and mutable objects in a class
  4. Execute a statement after thread gets over
  5. MSDN: ManualResetEvent Class

I know the below code is "wrong" as I abort each thread before I am assured the thread is finished. This is where a BackgroundWorker class or ManualResetEvent class might be useful. Furthermore, instantiating and running the threads in the GenerateValues function leads to a NULL object reference error; yet instantiating and running the threads in the CalculateSummary subroutine works fine. Ideally, the code implementation will use multiple threads in GenerateValues; but if that isn't possible, then I'm OK with removing that function entirely and adding its code to the subroutine. To expand my target audience, I wrote the code in both VB.NET—the language I actually use—and C#.

VB.NET:

Imports System.Threading

Public Class GroupSummary

    Public Sub CalculateSummary(ByVal pGroupKey As Integer)

        Dim records As DataTable = Nothing ///actually calls code that reads a database.
        Dim result As Integer = GenerateValues(records)
        ///code that inserts result into a database.
    End Sub

    Private Function GenerateValues(ByVal pRecords As DataTable) As Integer

        Dim numberHeightTall As Integer = 0
        Dim numberWeightHeavy As Integer = 0
        Dim numberFemale As Integer = 0
        Dim numberBlueEyes As Integer = 0
        Dim numberBob As Integer = 0
        Dim thread1 As New Thread(Sub() numberHeightTall =
                           CInt(pRecords.Compute("Count(NameID)", "Height > 72")))
        Dim thread2 As New Thread(Sub() numberWeightHeavy =
                           CInt(pRecords.Compute("Count(NameID)", "Weight > 200")))
        Dim thread3 As New Thread(Sub() numberFemale =
                           CInt(pRecords.Compute("Count(NameID)", "Female = True")))
        Dim thread4 As New Thread(Sub() numberBlueEyes =
                           CInt(pRecords.Compute("Count(NameID)", "EyeColor = 'Blue'")))
        Dim thread5 As New Thread(Sub() numberBob =
                           CInt(pRecords.Compute("Count(NameID)", "Name = 'Bob'")))
        thread1.Start()
        thread2.Start()
        thread3.Start()
        thread4.Start()
        thread5.Start()
        thread1.Abort()
        thread2.Abort()
        thread3.Abort()
        thread4.Abort()
        thread5.Abort()

        Return numberHeightTall + numberWeightHeavy + numberFemale + numberBlueEyes +
               numberBob
    End Function
End Class

C#:

using System.Threading;
using System.Data;
using System;

public class GroupSummary {

    public void CalculateSummary(int pGroupKey) {

        DataTable records = null; ///actually calls code that reads a database.

        int result = GenerateValues(records);

        ///code that inserts result into a database.
    }
    private int GenerateValues(DataTable pRecords) {

        int numberHeightTall = 0;
        int numberWeightHeavy = 0;
        int numberFemale = 0;
        int numberBlueEyes = 0;
        int numberBob = 0;
        Thread thread1 = new Thread(delegate () { numberHeightTall =
            Convert.ToInt32(pRecords.Compute("Count(NameID)", "Height > 72")); });
        Thread thread2 = new Thread(delegate () { numberWeightHeavy =
            Convert.ToInt32(pRecords.Compute("Count(NameID)", "Weight > 200")); });
        Thread thread3 = new Thread(delegate () { numberFemale =
            Convert.ToInt32(pRecords.Compute("Count(NameID)", "Female = True")); });
        Thread thread4 = new Thread(delegate () { numberBlueEyes =
            Convert.ToInt32(pRecords.Compute("Count(NameID)", "EyeColor = 'Blue'")); });
        Thread thread5 = new Thread(delegate () { numberBob =
            Convert.ToInt32(pRecords.Compute("Count(NameID)", "Name = 'Bob'")); });
        thread1.Start();
        thread2.Start();
        thread3.Start();
        thread4.Start();
        thread5.Start();
        thread1.Abort();
        thread2.Abort();
        thread3.Abort();
        thread4.Abort();
        thread5.Abort();

        return numberHeightTall + numberWeightHeavy + numberFemale + numberBlueEyes +
               numberBob;
    }
}
philomathic_life
  • 514
  • 3
  • 18

1 Answers1

1

As per the suggestion from KDecker, using the Task<TResult> class solved my question.

The following is a VB.NET implementation:

Imports System.Data

Public Class GroupSummary

    Public Sub CalculateSummary(ByVal pGroupKey As Integer)

        Dim records As DataTable = Nothing ///actually calls code that reads a database
        Dim result As Integer = GenerateValues(records)
        ///code that inserts result into database.
    End Sub

    Private Function GenerateValues(ByVal pRecords As DataTable) As Integer

        Dim tasks(4) As Task(Of Integer)
        tasks(0) = Task.Run(Function() CInt(pRecords.Compute(
                                        "Count(NameID)", "Height > 72")))
        tasks(1) = Task.Run(Function() CInt(pRecords.Compute(
                                        "Count(NameID)", "Weight > 200")))
        tasks(2) = Task.Run(Function() CInt(pRecords.Compute(
                                        "Count(NameID)", "Female = True")))
        tasks(3) = Task.Run(Function() CInt(pRecords.Compute(
                                        "Count(NameID)", "EyeColor = 'Blue'")))
        tasks(4) = Task.Run(Function() CInt(pRecords.Compute(
                                        "Count(NameID)", "Name = 'Bob'")))
        Task.WaitAll(tasks)

        Return tasks(0).Result + tasks(1).Result + tasks(2).Result + tasks(3).Result +
               tasks(4).Result
    End Function
End Class
philomathic_life
  • 514
  • 3
  • 18