none
Vb Multi Thread RRS feed

  • Question

  • I want to run multi threads for multi functions. I need to wait until all the threads have finished before I contenue but I want to run them parel to each other. For Example

    Thread A - Main Thread

    Thread B - Second Thread - Returns Data Table

    Thread C - Third Thread  - Returns Data Table

    Thread D - Fourth Thread - Returns Data Table

    I want to run threads a, b, c and d at the same time. Then I need to wait for threads b, c and d to complete. I'm a little newb to Async Await. If I use Async AWait can it run b,c, and d at the same time and wait until all three have finished? Anyone have a simple sample or code snippet? 

    Call to Function

    Data_dt = New Task(Async_LoadSummaryData("Order", sFacility))

    Currently gives errors and I dont know whats wrong 

    Function:

     Async Function Async_LoadSummaryData(ByVal StatusType As String, ByVal Filter As String, Optional ByVal Station As String = "", Optional ByVal AttrValue As String = "", Optional ByVal AttrValue2 As String = "", Optional ByVal AttrValue3 As String = "") As Task(Of DataTable)
            Dim dt As DataTable = New DataTable()
            dt = LoadSummaryData(StatusType, Filter, Station, AttrValue, AttrValue2, AttrValue3)
            Return dt
        End Function


    • Edited by old_School Tuesday, December 24, 2019 2:53 PM
    Tuesday, December 24, 2019 1:54 PM

All replies

  • Hello,

    If I may ask, why are you interested in loading four DataTable objects each in their own thread in parallel? Reason for asking is that doing this can be slower than conventional loading of DataTable objects plus when working with different threads you need to consider a) handling exceptions b) cancellations c) timeouts d) continuation back to the calling thread. You can look at ContinueWhenAll would be the way to go but this is going to add quite a bit of code  with no real gains, same with WhenAll.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, December 24, 2019 4:57 PM
    Moderator
  • Async and await are confusing. I am nearly certain that neither of them create threads, that threads must be crated by something else. Async and await are popular but not always necessary. In my opinion they sometimes make things unnecessarily complicated and when they do the old ways are easier to understand. See the following.

    There are many examples of those without use of async and await. For the thread class see the Thread.CurrentThread Property; there is an example there of creating many threads and storing their instances in a list and then using Task.WaitAll Method to wait for all of them.



    Sam Hobbs
    SimpleSamples.Info


    Tuesday, December 24, 2019 6:03 PM
  • Hi,
    try this console demo:

    Imports System.Data.SqlClient
    
    Module Module31
      Sub Main()
        Try
          Call (New Demo).Execute()
        Catch ex As Exception
          Console.WriteLine(ex.ToString)
        End Try
        Console.WriteLine("Continue enter key")
        Console.ReadKey()
      End Sub
    
      Friend Class Demo
    
        Friend Sub Execute()
          Dim ds As New DataSet
          Using cn As New SqlConnection(My.Settings.cnSQL & ";MultipleActiveResultSets=true;")
            cn.Open()
            Dim t1 = LoadDataSet("SELECT * FROM Tab1", cn)
            Dim t2 = LoadDataSet("SELECT * FROM Tab2", cn)
            Dim t3 = LoadDataSet("SELECT * FROM Tab1", cn)
            Task.WhenAll(New Task() {t1, t2, t3})
            ds.Tables.Add(t1.Result)
            ds.Tables.Add(t2.Result)
            ds.Tables.Add(t3.Result)
          End Using
          For Each t As DataTable In ds.Tables
            Console.WriteLine($"{t.Rows.Count}")
          Next
        End Sub
    
      End Class
    
      Private Function LoadDataSet(sql As String, cn As SqlConnection) As Task(Of DataTable)
        Dim rnd As New Random
        Return Task.Factory.StartNew(Of DataTable)(Function()
                                                     Dim dt As New DataTable
                                                     Using da As New SqlDataAdapter(sql, cn)
                                                       da.Fill(dt)
                                                       Threading.Thread.Sleep(rnd.Next(500, 2000)) ' simulate working time
                                                     End Using
                                                     Return dt
                                                   End Function)
      End Function
    
    End Module
    


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Tuesday, December 24, 2019 6:45 PM
  • Hi,
    try this console demo:

    Imports System.Data.SqlClient
    
    Module Module31
      Sub Main()
        Try
          Call (New Demo).Execute()
        Catch ex As Exception
          Console.WriteLine(ex.ToString)
        End Try
        Console.WriteLine("Continue enter key")
        Console.ReadKey()
      End Sub
    
      Friend Class Demo
    
        Friend Sub Execute()
          Dim ds As New DataSet
          Using cn As New SqlConnection(My.Settings.cnSQL & ";MultipleActiveResultSets=true;")
            cn.Open()
            Dim t1 = LoadDataSet("SELECT * FROM Tab1", cn)
            Dim t2 = LoadDataSet("SELECT * FROM Tab2", cn)
            Dim t3 = LoadDataSet("SELECT * FROM Tab1", cn)
            Task.WhenAll(New Task() {t1, t2, t3})
            ds.Tables.Add(t1.Result)
            ds.Tables.Add(t2.Result)
            ds.Tables.Add(t3.Result)
          End Using
          For Each t As DataTable In ds.Tables
            Console.WriteLine($"{t.Rows.Count}")
          Next
        End Sub
    
      End Class
    
      Private Function LoadDataSet(sql As String, cn As SqlConnection) As Task(Of DataTable)
        Dim rnd As New Random
        Return Task.Factory.StartNew(Of DataTable)(Function()
                                                     Dim dt As New DataTable
                                                     Using da As New SqlDataAdapter(sql, cn)
                                                       da.Fill(dt)
                                                       Threading.Thread.Sleep(rnd.Next(500, 2000)) ' simulate working time
                                                     End Using
                                                     Return dt
                                                   End Function)
      End Function
    
    End Module


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    You should show exception handling also especially considering working with a sub which can swallow an exception and even to the point of no exception thrown but instead having the app crash because the continuation is in a sense null/nothing.

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, December 24, 2019 7:14 PM
    Moderator
  • Hi Karen,
    the Exception will show in the try/catch calling Execute in the demo:

    Imports System.Data.SqlClient
    
    Module Module31
      Sub Main()
        Try
          Call (New Demo).Execute()
        Catch ex As Exception
          Dim ex1 = ex
          While ex1 IsNot Nothing
            Console.WriteLine(ex1.Message)
            ex1 = ex1.InnerException
          End While
        End Try
        Console.WriteLine("Continue enter key")
        Console.ReadKey()
      End Sub
    
      Friend Class Demo
    
        Friend Sub Execute()
          Dim ds As New DataSet
          Using cn As New SqlConnection(My.Settings.cnSQL & ";MultipleActiveResultSets=true;")
              cn.Open()
              Dim t1 = LoadDataSet("SELECT * FROM Tab1", cn)
              Dim t2 = LoadDataSet("SELECT * FROM Tab2", cn)
              Dim t3 = LoadDataSet("SELECT * FROM Tab1", cn)
              Task.WhenAll(New Task() {t1, t2, t3})
              ds.Tables.Add(t1.Result)
              ds.Tables.Add(t2.Result)
              ds.Tables.Add(t3.Result)
            End Using
            For Each t As DataTable In ds.Tables
              Console.WriteLine($"{t.Rows.Count}")
            Next
        End Sub
    
      End Class
    
      Private Function LoadDataSet(sql As String, cn As SqlConnection) As Task(Of DataTable)
        Dim rnd As New Random
        Return Task.Factory.StartNew(Of DataTable)(Function()
                                                     Dim dt As New DataTable
                                                     Using da As New SqlDataAdapter(sql, cn)
                                                       da.Fill(dt)
                                                       Threading.Thread.Sleep(rnd.Next(500, 2000)) ' simulate working time
                                                       Throw New Exception("Exeption in Thread")
                                                     End Using
                                                     Return dt
                                                   End Function)
      End Function
    
    End Module
    The better way is to check the Exception property in Task object.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Tuesday, December 24, 2019 7:47 PM
  • Hi,

    WhenAll returns a Task. When you call this method it returns a task that is waiting for all the tasks to complete. 

    If you want to  know when all tasks complete but not actually block your code then use WhenAll.

    Hope it be helpful.

    Best Regards,

    Julie


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, December 25, 2019 6:57 AM
    Moderator
  • ...

    You can only use one datareader on one connection.

    ...

    Hi,
    SQL Server supports MultipleActiveResultSets=true. Using this parameter you can execute more then one DataReader with the same connection at the same time.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Saturday, December 28, 2019 2:49 PM