Results 1 to 38 of 38

Thread: Update database records using multiple threads

  1. #1

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Update database records using multiple threads

    Gents,
    Been a while since I did any VB work, and have started a new project that is a Windows Service that will update a database using multiple threads. I am testing this out with a dataset that consists of a "device name" and a "device IP", pinging the device, and attempting to update the device's "status".

    I have it working in a single-thread type configuration, but would like to be able to ping and update different records across multiple threads (for obvious reasons).

    The problem I'm having is with the logic mainly. When the service is started, I get all the devices from the database and fill a DataSet. From there, I am looping through the dataset's rows, pinging each device and updating the record. I know how to spawn multiple threads, but I do not know how to keep track of updating the correct record and also making sure that all records are checked in some kind of order. Like, if user specifies 5 threads, I need it to get record 1, thread finishes, gets record 6 (while other threads execute), or something like that.

    What's the best approach here.

    Note: this does no interface updating or anything like that. Only updates a database record's field value.

    Thanks in advance!

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Do you really need to let the user specify the number of simultaneous operations? Generally speaking, it's better to simply use the ThreadPool and let the system handle scheduling.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Re: Update database records using multiple threads

    Hey JMC, good to see you're still on the board!

    I just finished getting a ThreadPool version working and seems to be working properly. Got a little stuck with passing a value to the procedure being executed by the Thread, but wrapping it in a separate small class did the trick. Still very new to the mutli-threading stuff, but am understanding the concept a little bit more with each example I come across.

    Code:
    objEventLog.WriteEntry("Scanning Started")
            For Each row As DataRow In ds.Tables("Devices").Rows
                rowIndex += 1
                Dim ti As New TaskInfo(row(2), rowIndex)
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartScan), ti)
    
                If rowIndex > ds.Tables("Devices").Rows.Count - 1 Then
                    objEventLog.WriteEntry("Scan Completed at " & Date.Now)
                    Exit For
                End If
            Next
    One thing I can't figure out is how to tell when my "scan" is completed (ie: all threads have completed, so that I can reset my variables to "loop" it). I don't see any ThreadPool features that do this.

    Also, side question, does the "SyncLock" thing only come into play when a UI is involved?

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by stateofidleness View Post
    One thing I can't figure out is how to tell when my "scan" is completed (ie: all threads have completed, so that I can reset my variables to "loop" it). I don't see any ThreadPool features that do this.
    You might want to check out this discussion that involves the use of WaitHandles.

    http://www.vbforums.com/showthread.php?t=630107
    Quote Originally Posted by stateofidleness View Post
    Also, side question, does the "SyncLock" thing only come into play when a UI is involved?
    SyncLock has nothing specifically to do with a UI thread. You would use it any time that you have a critical section, i.e. a block of code that must be executed by no more than one thread at a time.

    For instance, if you have code that increments a variable and then uses the value, it would be possible for two threads to interfere with each other without a SyncLock. The first thread might increment the variable and then be switched out and the second thread increment the variable and then be switched and then have the first thread use the value that has been incremented twice instead of once.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Wouldn't it be better to package the functionality within a class and give it progress and completed type events ? I find that usually its the best design for asynchronous tasks.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    Wouldn't it be better to package the functionality within a class and give it progress and completed type events ? I find that usually its the best design for asynchronous tasks.
    If it was a complex app and/or the code was to be re-used then yes, I would absolutely suggest that. If it's just a simple app and the code will be used in one place then, while it would certainly not be wrong to do so, I wouldn't bother.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    Wouldn't it be better to package the functionality within a class and give it progress and completed type events ? I find that usually its the best design for asynchronous tasks.
    I'm not sure what functionality specifically you're suggesting I package in its own class. Currently, I'm receiving a list of devices at Service start, then iterating through the dataset to ping each device (each ping using a thread in the ThreadPool).

    Eventually, this ping will be changed to do more complex and time-consuming tasks for each device, but not sure what exactly should be put it its own class.

    JMC, that thread was wayyyy over my head

  8. #8
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Quote Originally Posted by stateofidleness View Post
    I'm not sure what functionality specifically you're suggesting I package in its own class.
    This is what I mean:-
    vbnet Code:
    1. 'Imagine this class to be a class used
    2. 'to represent each device retrieved from the database
    3. Public Class Device
    4.     Private _DeviceID As Integer
    5.     Private _DeviceName As String
    6.     Private _SomeDeviceProperty As Integer
    7.  
    8.     Private g_bPingingAsync As Boolean = False
    9.  
    10.     'This control would be used to invoke on the thread
    11.     'on which this object was created
    12.     'The idea being that we raise events there
    13.     Private g_objControl As Control
    14.  
    15.     Public Event PingProgressChanged As EventHandler(Of PingProgressChangedEventArgs)
    16.     Protected Overridable Sub OnPingProgressChanged(ByVal e As PingProgressChangedEventArgs)
    17.         RaiseEvent PingProgressChanged(Me, e)
    18.     End Sub
    19.  
    20.     Public Event PingProgressCompleted As EventHandler
    21.     Protected Overridable Sub OnPingProgressCompleted()
    22.         RaiseEvent PingProgressCompleted(Me, New EventArgs)
    23.     End Sub
    24.  
    25.     Sub New()
    26.         g_objControl = New Control
    27.  
    28.         'Force handle creation current thread
    29.         'so we can invoke on this thread.
    30.         Dim x As IntPtr = g_objControl.Handle
    31.  
    32.     End Sub
    33.  
    34.     Sub New(ByVal devName As String, ByVal devID As Integer, ByVal someProp As Integer)
    35.         MyClass.New()
    36.  
    37.         Me.DeviceID = devID
    38.         Me.DeviceName = devName
    39.         Me.SomeDeviceProperty = someProp
    40.  
    41.     End Sub
    42.  
    43.     Public Property DeviceID() As Integer
    44.         Get
    45.             Return _DeviceID
    46.         End Get
    47.         Set(ByVal value As Integer)
    48.             _DeviceID = value
    49.         End Set
    50.     End Property
    51.     Public Property DeviceName() As String
    52.         Get
    53.             Return _DeviceName
    54.         End Get
    55.         Set(ByVal value As String)
    56.             _DeviceName = value
    57.         End Set
    58.     End Property
    59.     Public Property SomeDeviceProperty() As Integer
    60.         Get
    61.             Return _SomeDeviceProperty
    62.         End Get
    63.         Set(ByVal value As Integer)
    64.             _SomeDeviceProperty = value
    65.         End Set
    66.     End Property
    67.  
    68.     Public Sub PingDevice()
    69.         InternalPingDevice()
    70.     End Sub
    71.  
    72.     Public Sub PingDeviceAsync()
    73.         If g_bPingingAsync Then
    74.             Throw New Exception("Alreadying pinging asyncrounously")
    75.         End If
    76.  
    77.         g_bPingingAsync = True
    78.         ThreadPool.QueueUserWorkItem(AddressOf InternalPingDevice, Nothing)
    79.     End Sub
    80.  
    81.     Private Sub InternalPingDevice()
    82.  
    83.         Dim i As Integer = 0
    84.         Dim e As PingProgressChangedEventArgs
    85.  
    86.         'Imagine this For...Next loop is your pinging process
    87.         '----------------------------------------------------
    88.         For i = 0 To Me.SomeDeviceProperty
    89.  
    90.             Thread.Sleep(200)
    91.  
    92.             e = New PingProgressChangedEventArgs((i / Me.SomeDeviceProperty) * 100)
    93.  
    94.             'If this sub was called on any thread other than the one
    95.             'where it was created then we invoke the event handlers
    96.             'on the control's thread
    97.             If g_objControl.InvokeRequired Then
    98.                 g_objControl.Invoke(New Action(Of PingProgressChangedEventArgs)(AddressOf OnPingProgressChanged), e)
    99.             Else
    100.                 OnPingProgressChanged(e)
    101.             End If
    102.  
    103.         Next
    104.  
    105.         g_bPingingAsync = False
    106.  
    107.         If g_objControl.InvokeRequired Then
    108.             g_objControl.Invoke(New Action(AddressOf OnPingProgressCompleted))
    109.         Else
    110.             OnPingProgressCompleted()
    111.         End If
    112.     End Sub
    113.  
    114.  
    115. End Class
    116.  
    117. Public Class PingProgressChangedEventArgs
    118.     Inherits EventArgs
    119.  
    120.     Private _progress As Integer
    121.  
    122.     Sub New(ByVal progressPercent As Integer)
    123.         Me.Progress = progressPercent
    124.     End Sub
    125.  
    126.     Public Property Progress() As Integer
    127.         Get
    128.             Return _progress
    129.         End Get
    130.         Set(ByVal value As Integer)
    131.             _progress = value
    132.         End Set
    133.     End Property
    134.  
    135. End Class

    The pinging itself is represented and implemented in a Class that represents a single device. You can then call the ping on each device in a list created from data received from a database. This is the idea I'm getting at.

    I've attached a complete implementation of a simulation based on what you described. Just click the Start Pinging button on the Form and see what happens. Each ping operation is performed on a separate thread pool thread. Observe how I handle both the completion of the ping operation of each device and the completion of all ping operations.
    Attached Files Attached Files
    Last edited by Niya; May 29th, 2012 at 12:11 AM. Reason: More Info.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  9. #9

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Re: Update database records using multiple threads

    Man, that looks pretty awesome, but it uses a lot of stuff I'm not familiar with (like BindingList). What's the "g_" convention?

    I really don't know how this works
    Is the example actually pinging things?

    maybe i'm out of my league here lol

    I like the idea of using a "Device" class as it's something I think I could use in other projects, but I'm not sure how to get the dataset and the class to "talk".

  10. #10
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    "g_" is a convention I personally use to represent private fields, sometimes referred to as module level variables.

    Think of a BindingList(Of T) as a special List(Of T) object that is designed specifically for data binding. You can replace the BindingList with a List if you want since I didn't use it here for anything more than display purposes so it doesn't really need all the special functionality.

    but I'm not sure how to get the dataset and the class to "talk".
    You don't actually, you would use the data from the DataSet to instantiate Device objects.

    Is the example actually pinging things?
    No, its just a simulation to demonstrate multithreading.

    Anything else you don't understand about it ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  11. #11

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Re: Update database records using multiple threads

    Good deal, let me play with this for a bit and give it a good study. If any questions come up, i'll post back!

  12. #12
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Aite, good luck
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  13. #13
    Frenzied Member
    Join Date
    Jul 2006
    Location
    MI
    Posts
    2,012

    Re: Update database records using multiple threads

    How about using a Parallel.For loop?

  14. #14
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    Niya - wow - what a nice example!! It's saying I have to spread some rep around - otherwise I'd be rep'ing you now!

    For me it all boils down to this code...

    Code:
    AddHandler dev.PingProgressChanged, AddressOf PingProgressChangedEventHandler
    Ability to have a function run on the calling thread when an event in the class is raised is exactly what I'm looking to do right now in a service app I'm writing.

    Running your sample app made it all make perfect sense instantly!

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  15. #15
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Thx . Glad you you liked it.

    You understand how I got the events to be raised on the UI thread from the Device class?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  16. #16
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    Yup - I set break points all over the place and watched and saw how it all went down. Very nice.

    Quick question - why a BINDINGLIST(Of) instead of a LIST(Of)???

    I'm developing an app - a central service running on a network. All the UI's running on the network send "requests" to the service which is going to create a LIST(Of) my "processing class" and run some async method within that class.

    When the async method complete the calling service needs to examine the results and send info back to the UI's.

    As the UI's amend their request the "processing class" that I create for each UI will alter some properties on that class and then run some more async methods.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  17. #17
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    For this example a BindingList(Of T) wasn't necessary. A List(Of T) would have sufficed.

    A BindingList(Of T) is exactly like a List(Of T) except that it has events that are used to detect changes in the items of the list and changes to the list itself. If you use a List(Of T) in a data-binding scenario, you would find that bound controls would not detect these changes and update their display. In my example, I don't alter anything in the list of Devices after binding so a BindingList wasn't really necessary.

    A BindingList(Of T) also allows a bound DataGridView to add rows to the list should they desire such. A List(Of T) doesn't.

    This project you're working on, are you passing .Net objects across the network ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  18. #18
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    Yes - I am serializing and de-serializing a "transmission" class among a UI app (running multiple times on a network) and three background "service" apps - all using HttpListener methods.

    I am really enjoying this type of coding - it's not paying yet but we have hopes!

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  19. #19
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Sweet Its good to get paid for something you like Good luck.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  20. #20
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    You understand how I got the events to be raised on the UI thread from the Device class?
    You appear to be creating a Control of your own. You should rather be using the SynchronizationContext class.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  21. #21
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    Quote Originally Posted by jmcilhinney View Post
    You appear to be creating a Control of your own. You should rather be using the SynchronizationContext class.
    Would that be the .Send and .Post methods of that class? Is that how it would raise event code to be run on a different thread?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  22. #22
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by szlamany View Post
    Would that be the .Send and .Post methods of that class? Is that how it would raise event code to be run on a different thread?
    Correct. Send is analogous to Invoke and Post is analogous to BeginInvoke. There are examples of using SynchronizationContext in a couple of my CodeBank threads: Accessing Controls From Worker Threads and also Asynchronous TCP.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  23. #23

    Thread Starter
    Frenzied Member stateofidleness's Avatar
    Join Date
    Jan 2009
    Posts
    1,780

    Re: Update database records using multiple threads

    Niya, I think what threw me off at first was the use of a UI in the example. I'm working with a Windows Service that will update a database. The front-end will be a web-based UI (PHP). I may add a Windows Form front-end at some point, but do the same "rules" apply to a non-Form type service? (ie: can I still raise events and know when they complete, etc?)

    I'm not really familiar with this syntax format:
    AddHandler dev.PingProgressChanged, AddressOf PingProgressChangedEventHandler

    What's that saying in "pseudo" code terms?

  24. #24
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Quote Originally Posted by jmcilhinney View Post
    You appear to be creating a Control of your own. You should rather be using the SynchronizationContext class.
    I donno. It seems to do much more than I really need and it looks a little intimidating considering all I want to do is invoke a delegate on the UI thread. Using a Control object is elegantly simpler it seems but of course I've never used the SynchronizationContext so I don't really know. I'll experiment with this at a later time and see what its about.

    EDIT:

    Oh you posted while I was typing this. Can that SynchronizationContext object be used with my approach without significant modifications ?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  25. #25
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Quote Originally Posted by stateofidleness View Post
    Niya, I think what threw me off at first was the use of a UI in the example. I'm working with a Windows Service that will update a database. The front-end will be a web-based UI (PHP). I may add a Windows Form front-end at some point, but do the same "rules" apply to a non-Form type service? (ie: can I still raise events and know when they complete, etc?)

    I'm not really familiar with this syntax format:
    AddHandler dev.PingProgressChanged, AddressOf PingProgressChangedEventHandler

    What's that saying in "pseudo" code terms?
    Ya you can use the pattern without a UI if you want. It won't cause any problems.

    Here is the documentation for AddHandler. It attaches event handlers to object events.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  26. #26
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    Oh you posted while I was typing this. Can that SynchronizationContext object be used with my approach without significant modifications ?
    There would be some change but not much. One advantage with a SynchronizationContext is that it will work in WPF without change and also in non-GUI scenarios, where creating a control would be quite wrong.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  27. #27
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Hmm, I see. I think I'll try to rework my example to use it. It looks so intimidating , I'll post it up here when I get through.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  28. #28
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    It looks so intimidating
    It's not, e.g.
    vb.net Code:
    1. Public Class SomeClass
    2.  
    3.     'This will get the context for the current thread so this instance must be created on the UI thread for a GUI app.
    4.     Private context As SynchronizationContext = SynchronizationContext.Current
    5.  
    6.     Public Event SomeEvent As EventHandler
    7.  
    8.     Private Sub RaiseSomeEvent()
    9.         If context Is Nothing Then
    10.             'This is not a GUI app so raise the event on the current thread.
    11.             OnSomeEvent(EventArgs.Empty)
    12.         Else
    13.             'This is a GUI app so raise the event on the UI thread.
    14.             context.Send(Sub() OnSomeEvent(EventArgs.Empty), Nothing)
    15.         End If
    16.     End Sub
    17.  
    18.     Protected Overridable Sub OnSomeEvent(e As EventArgs)
    19.         RaiseEvent SomeEvent(Me, e)
    20.     End Sub
    21.  
    22. End Class
    EDIT: Note that the action Lambda used as an argument to Send requires .NET 4.0 or later but you can easily enough do the equivalent with a named method in an earlier version.
    Last edited by jmcilhinney; May 29th, 2012 at 08:56 PM.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  29. #29
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Oh, I get it now. Its used almost the same way I use Control.Invoke
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  30. #30
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Ok, I worked it into the Device class in my example. It works!:-
    vbnet Code:
    1. '
    2. Public Class Device
    3.     Private _DeviceID As Integer
    4.     Private _DeviceName As String
    5.     Private _SomeDeviceProperty As Integer
    6.  
    7.     Private g_bPingingAsync As Boolean = False
    8.  
    9.     Private context As SynchronizationContext = SynchronizationContext.Current
    10.  
    11.     Public Event PingProgressChanged As EventHandler(Of PingProgressChangedEventArgs)
    12.     Protected Overridable Sub OnPingProgressChanged(ByVal e As PingProgressChangedEventArgs)
    13.         RaiseEvent PingProgressChanged(Me, e)
    14.     End Sub
    15.  
    16.     Public Event PingProgressCompleted As EventHandler
    17.     Protected Overridable Sub OnPingProgressCompleted()
    18.         RaiseEvent PingProgressCompleted(Me, New EventArgs)
    19.     End Sub
    20.  
    21.     Sub New()
    22.    
    23.     End Sub
    24.  
    25.     Sub New(ByVal devName As String, ByVal devID As Integer, ByVal someProp As Integer)
    26.         MyClass.New()
    27.  
    28.         Me.DeviceID = devID
    29.         Me.DeviceName = devName
    30.         Me.SomeDeviceProperty = someProp
    31.  
    32.     End Sub
    33.  
    34.     Public Property DeviceID() As Integer
    35.         Get
    36.             Return _DeviceID
    37.         End Get
    38.         Set(ByVal value As Integer)
    39.             _DeviceID = value
    40.         End Set
    41.     End Property
    42.     Public Property DeviceName() As String
    43.         Get
    44.             Return _DeviceName
    45.         End Get
    46.         Set(ByVal value As String)
    47.             _DeviceName = value
    48.         End Set
    49.     End Property
    50.     Public Property SomeDeviceProperty() As Integer
    51.         Get
    52.             Return _SomeDeviceProperty
    53.         End Get
    54.         Set(ByVal value As Integer)
    55.             _SomeDeviceProperty = value
    56.         End Set
    57.     End Property
    58.  
    59.     Public Sub PingDevice()
    60.         InternalPingDevice()
    61.     End Sub
    62.  
    63.     Public Sub PingDeviceAsync()
    64.         If g_bPingingAsync Then
    65.             Throw New Exception("Alreadying pinging asyncrounously")
    66.         End If
    67.  
    68.         g_bPingingAsync = True
    69.         ThreadPool.QueueUserWorkItem(AddressOf InternalPingDevice, Nothing)
    70.     End Sub
    71.  
    72.     Private Sub InternalPingDevice()
    73.  
    74.         Dim i As Integer = 0
    75.         Dim e As PingProgressChangedEventArgs
    76.  
    77.         'Imagine this For...Next loop is your pinging process
    78.         '----------------------------------------------------
    79.         For i = 0 To Me.SomeDeviceProperty
    80.  
    81.             Thread.Sleep(200)
    82.  
    83.             e = New PingProgressChangedEventArgs((i / Me.SomeDeviceProperty) * 100)
    84.  
    85.  
    86.             If context Is Nothing Then
    87.                 OnPingProgressChanged(e)
    88.             Else
    89.                 context.Send(New SendOrPostCallback(AddressOf OnPingProgressChanged), e)
    90.             End If
    91.  
    92.         Next
    93.  
    94.         g_bPingingAsync = False
    95.  
    96.         If context Is Nothing Then
    97.             OnPingProgressCompleted()
    98.         Else
    99.             context.Send(New SendOrPostCallback(AddressOf OnPingProgressCompleted), Nothing)
    100.         End If
    101.  
    102.     End Sub
    103.  
    104.  
    105. End Class

    While it is quite similar to what I had before, I have to say that I find Invoke to be a superior function for the simple reason it takes a paramarray for the arguments of the delegate and it can use a delegate of any signature. Send is far too limited. Its a good thing that OnEvent type methods only take one parameter of an EventArgs class else it could have gotten real clumsy. The Send method should have had the same signature as Invoke, donno why MS didn't do it so.
    Last edited by Niya; May 29th, 2012 at 09:24 PM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  31. #31
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    While it is quite similar to what I had before, I have to say that I find Invoke to be a superior function for the simple reason it takes a paramarray for the arguments of the delegate and it can use a delegate of any signature. Send is far too limited. Its a good thing that OnEvent type methods only take one parameter of an EventArgs class else it could have gotten real clumsy. The Send method should have had the same signature as Invoke, donno why MS didn't do it so.
    I actual fact, the code you posted won't work with Option Strict On, which it should always be, because the SendOrPostCallback has a single Object parameter, just like most methods related to multi-threading do. That's why it's preferable to use a Lambda. My example could look like this without the Lambda:
    vb.net Code:
    1. Public Class SomeClass
    2.  
    3.     'This will get the context for the current thread so this instance must be created on the UI thread.
    4.     Private context As SynchronizationContext = SynchronizationContext.Current
    5.  
    6.     Public Event SomeEvent As EventHandler
    7.  
    8.     Private Sub RaiseSomeEvent()
    9.         If context Is Nothing Then
    10.             'This is not a GUI app so raise the event on the current thread.
    11.             RaiseSomeEvent(EventArgs.Empty)
    12.         Else
    13.             'This is a GUI app so raise the event on the UI thread.
    14.             context.Send(AddressOf RaiseSomeEvent, EventArgs.Empty)
    15.         End If
    16.     End Sub
    17.  
    18.     Private Sub RaiseSomeEvent(e As Object)
    19.         OnSomeEvent(DirectCast(e, EventArgs))
    20.     End Sub
    21.  
    22.     Protected Overridable Sub OnSomeEvent(e As EventArgs)
    23.         RaiseEvent SomeEvent(Me, e)
    24.     End Sub
    25.  
    26. End Class
    All you need is the one extra method with an Object parameter that casts it as the appropriate type and then calls the final method. Three extra lines of code.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  32. #32
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    @niya - thanks - I worked your changes for this stuff:

    Private context As SynchronizationContext = SynchronizationContext.Current

    Into your sample app - worked perfectly. I was able to rep you also - thanks again!

    @jmc - good stuff you added here for us. Also - I really appreciate seeing lambda examples

    Quick question - doing this:

    context.Send(Sub() OnSomeEvent(EventArgs.Empty), Nothing)

    Does that go into OnSomeEvent with a reference to the calling function - kind of like the THIS in Javascript and how closure works to make local declarations live into the called function?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  33. #33
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    vbnet Code:
    1. context.Send(Sub() OnSomeEvent(EventArgs.Empty), Nothing)
    The above is the same as doing:-
    vbnet Code:
    1. '
    2.     Sub AnonymousSub()
    3.         OnSomeEvent(EventArgs.Empty)
    4.     End Sub
    5.    
    6.     context.Send(AddressOf AnonymousSub,Nothing)

    In fact, that's exactly what the compiler does when you use Lambda expressions. Lambdas are a more succinct way of doing it.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  34. #34
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    Quote Originally Posted by jmcilhinney View Post
    I actual fact, the code you posted won't work with Option Strict On, which it should always be, because the SendOrPostCallback has a single Object parameter, just like most methods related to multi-threading do. That's why it's preferable to use a Lambda. My example could look like this without the Lambda:
    vb.net Code:
    1. Public Class SomeClass
    2.  
    3.     'This will get the context for the current thread so this instance must be created on the UI thread.
    4.     Private context As SynchronizationContext = SynchronizationContext.Current
    5.  
    6.     Public Event SomeEvent As EventHandler
    7.  
    8.     Private Sub RaiseSomeEvent()
    9.         If context Is Nothing Then
    10.             'This is not a GUI app so raise the event on the current thread.
    11.             RaiseSomeEvent(EventArgs.Empty)
    12.         Else
    13.             'This is a GUI app so raise the event on the UI thread.
    14.             context.Send(AddressOf RaiseSomeEvent, EventArgs.Empty)
    15.         End If
    16.     End Sub
    17.  
    18.     Private Sub RaiseSomeEvent(e As Object)
    19.         OnSomeEvent(DirectCast(e, EventArgs))
    20.     End Sub
    21.  
    22.     Protected Overridable Sub OnSomeEvent(e As EventArgs)
    23.         RaiseEvent SomeEvent(Me, e)
    24.     End Sub
    25.  
    26. End Class
    All you need is the one extra method with an Object parameter that casts it as the appropriate type and then calls the final method. Three extra lines of code.
    Oh, I almost forgot to post this up...wrote it and fell asleep after:-
    vbnet Code:
    1. Option Strict On
    2. Imports System.Threading
    3. Imports System.Runtime.CompilerServices
    4.  
    5. 'Imagine this class to be a class used
    6. 'to represent each device retrieved from the database
    7. Public Class Device
    8.     Private _DeviceID As Integer
    9.     Private _DeviceName As String
    10.     Private _SomeDeviceProperty As Integer
    11.  
    12.     Private g_bPingingAsync As Boolean = False
    13.  
    14.     Private context As SynchronizationContext = SynchronizationContext.Current
    15.  
    16.     Public Event PingProgressChanged As EventHandler(Of PingProgressChangedEventArgs)
    17.     Protected Overridable Sub OnPingProgressChanged(ByVal e As PingProgressChangedEventArgs)
    18.         RaiseEvent PingProgressChanged(Me, e)
    19.     End Sub
    20.  
    21.     Public Event PingProgressCompleted As EventHandler
    22.     Protected Overridable Sub OnPingProgressCompleted()
    23.         RaiseEvent PingProgressCompleted(Me, New EventArgs)
    24.     End Sub
    25.  
    26.     Sub New()
    27.  
    28.     End Sub
    29.  
    30.     Sub New(ByVal devName As String, ByVal devID As Integer, ByVal someProp As Integer)
    31.         MyClass.New()
    32.  
    33.         Me.DeviceID = devID
    34.         Me.DeviceName = devName
    35.         Me.SomeDeviceProperty = someProp
    36.  
    37.     End Sub
    38.  
    39.     Public Property DeviceID() As Integer
    40.         Get
    41.             Return _DeviceID
    42.         End Get
    43.         Set(ByVal value As Integer)
    44.             _DeviceID = value
    45.         End Set
    46.     End Property
    47.     Public Property DeviceName() As String
    48.         Get
    49.             Return _DeviceName
    50.         End Get
    51.         Set(ByVal value As String)
    52.             _DeviceName = value
    53.         End Set
    54.     End Property
    55.     Public Property SomeDeviceProperty() As Integer
    56.         Get
    57.             Return _SomeDeviceProperty
    58.         End Get
    59.         Set(ByVal value As Integer)
    60.             _SomeDeviceProperty = value
    61.         End Set
    62.     End Property
    63.  
    64.     Public Sub PingDevice()
    65.         InternalPingDevice()
    66.     End Sub
    67.  
    68.     Public Sub PingDeviceAsync()
    69.         If g_bPingingAsync Then
    70.             Throw New Exception("Alreadying pinging asyncrounously")
    71.         End If
    72.  
    73.         g_bPingingAsync = True
    74.         ThreadPool.QueueUserWorkItem(AddressOf InternalPingDevice, Nothing)
    75.     End Sub
    76.  
    77.     Private Sub InternalPingDevice()
    78.         InternalPingDevice(Nothing)
    79.     End Sub
    80.  
    81.     Private Sub InternalPingDevice(ByVal state As Object)
    82.  
    83.         Dim i As Integer = 0
    84.         Dim e As PingProgressChangedEventArgs
    85.  
    86.         'Imagine this For...Next loop is your pinging process
    87.         '----------------------------------------------------
    88.         For i = 0 To Me.SomeDeviceProperty
    89.  
    90.             Thread.Sleep(200)
    91.  
    92.             e = New PingProgressChangedEventArgs(CInt((i / Me.SomeDeviceProperty) * 100))
    93.  
    94.             If context Is Nothing Then
    95.                 OnPingProgressChanged(e)
    96.             Else
    97.                 context.Invoke(New Action(Of PingProgressChangedEventArgs)(AddressOf OnPingProgressChanged), e)
    98.                 'context.Send(New SendOrPostCallback(AddressOf OnPingProgressChanged), e)
    99.             End If
    100.  
    101.         Next
    102.  
    103.         g_bPingingAsync = False
    104.  
    105.         If context Is Nothing Then
    106.             OnPingProgressCompleted()
    107.         Else
    108.             'context.Send(New SendOrPostCallback(AddressOf OnPingProgressCompleted), Nothing)
    109.             context.Invoke(New Action(AddressOf OnPingProgressCompleted))
    110.         End If
    111.  
    112.     End Sub
    113.  
    114.  
    115.  
    116. End Class
    117.  
    118. Public Class PingProgressChangedEventArgs
    119.     Inherits EventArgs
    120.  
    121.     Private _progress As Integer
    122.  
    123.     Sub New(ByVal progressPercent As Integer)
    124.         Me.Progress = progressPercent
    125.     End Sub
    126.  
    127.     Public Property Progress() As Integer
    128.         Get
    129.             Return _progress
    130.         End Get
    131.         Set(ByVal value As Integer)
    132.             _progress = value
    133.         End Set
    134.     End Property
    135.  
    136. End Class
    137.  
    138. Public Module Extensions
    139.  
    140.     <Extension()> _
    141.     Public Sub Invoke(ByVal sc As SynchronizationContext, ByVal del As [Delegate], ByVal ParamArray args() As Object)
    142.         sc.Send(New SendOrPostCallback(AddressOf SendOrPost), New SendOrPostState With {.Args = args, .DelegateToInvoke = del})
    143.     End Sub
    144.  
    145.     Private Sub SendOrPost(ByVal state As Object)
    146.         Dim st As SendOrPostState = DirectCast(state, SendOrPostState)
    147.  
    148.         st.DelegateToInvoke.DynamicInvoke(st.Args)
    149.     End Sub
    150.  
    151.  
    152.     Private Class SendOrPostState
    153.         Public Args() As Object
    154.         Public DelegateToInvoke As [Delegate]
    155.  
    156.     End Class
    157.  
    158. End Module

    I'm using VS 2008 so I can't use Sub to create a lambda expression and I don't really like the idea of having to declare an extra OnEvent type procedure just to support Send so I created an Invoke extension method for the SynchronizationContext class which works like the Invoke method on the Control class. This way works with Option Strict.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  35. #35
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    Quote Originally Posted by Niya View Post
    I created an Invoke extension method for the SynchronizationContext class which works like the Invoke method on the Control class. This way works with Option Strict.
    Haven't tested it but that's a nice touch.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  36. #36
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Update database records using multiple threads

    @jmc - I had asked a question back a few weeks ago in this post from up above - did you see it?

    Quote Originally Posted by szlamany View Post
    @niya - thanks - I worked your changes for this stuff:

    Private context As SynchronizationContext = SynchronizationContext.Current

    Into your sample app - worked perfectly. I was able to rep you also - thanks again!

    @jmc - good stuff you added here for us. Also - I really appreciate seeing lambda examples

    Quick question - doing this:

    context.Send(Sub() OnSomeEvent(EventArgs.Empty), Nothing)

    Does that go into OnSomeEvent with a reference to the calling function - kind of like the THIS in Javascript and how closure works to make local declarations live into the called function?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  37. #37
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Update database records using multiple threads

    To be honest, I'm not sure of all the internal details.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  38. #38
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Update database records using multiple threads

    I'm not sure but I think what he is asking is if you can use local variable from where the lambda is created. If so the answer is yes.
    vbnet Code:
    1. '
    2.         Dim x As Integer = 3
    3.  
    4.         Dim mylambda As Func(Of DialogResult) = Function() MsgBox(CStr(x + 1))
    5.  
    6.         mylambda()

    The above would show a message box with '4'.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width