mattsrebatespam Posted February 17, 2005 Posted February 17, 2005 I am trying to get multithreading working for a project. I have created a test app so I can figure out the multithreading without having to worry about other issues. I have an arraylist that contains the numbers 1-100. I want to square those numbers and add them to a listbox. The problem I am having is that it runs though each thread one time and then it dies. I get errors about the thread unable to restart. I tried putting suspend and interrupt command in the background process but nothing helped so far. Any ideas? Here is the code I am using: Public ThreadControl1 As Thread = New Thread(AddressOf Me.BackgroundProcess) Public ThreadControl2 As Thread = New Thread(AddressOf Me.BackgroundProcess) Public ThreadControl3 As Thread = New Thread(AddressOf Me.BackgroundProcess) Public ThreadControl4 As Thread = New Thread(AddressOf Me.BackgroundProcess) Public SquareArrayList As New ArrayList Public i As Integer Private Sub BackgroundProcess() listbox1.Items.Add(SquareArrayList.Item(i) & " " & SquareArrayList.Item(i) * SquareArrayList.Item(i)) i += 1 End Sub Private Sub StartClick(sender As System.Object, e As System.EventArgs) Do While i < SquareArrayList.Count ThreadControl1.Start() ThreadControl2.Start() ThreadControl3.Start() ThreadControl4.Start() Loop End Sub Quote
Mike_R Posted February 18, 2005 Posted February 18, 2005 (edited) Funny... I just started learning Threading just a few mins. ago and I'm struggling with some of the same issues. Here's what I've figured out so far: (1) Don't use Thread.Sleep and Thread.Interrupt when called externally, as it seems a bit less "safe". Use Thread.Suspend and Thread.Resume instead. (2) You must check the Thread.ThreadState before doing your commands. Why? Because if you call Thread.Start() again after it's already Running, then it will error out. Similarly, calling Thread.Suspend when it's already suspended would be a no-no.. So see the attached project that I was kicking around. It is really a noobie Threading project, to be sure... and represents 100% of my knowledge on this subject! (Yeah pretty weak...) But hopefully it will be of value to you. The project itself is attached, but the code is pretty simple:Public Class Form1 Inherits System.Windows.Forms.Form Sub DoIt() For i As Integer = 0 To 1000000000 Me.lblResults.Text = i.ToString("N0") Next End Sub Dim oThread As System.Threading.Thread Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click If oThread Is Nothing Then oThread = New Threading.Thread(AddressOf DoIt) oThread.Start() End If End Sub Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click If Not oThread Is Nothing Then If oThread.ThreadState = Threading.ThreadState.Suspended Then oThread.Resume() oThread.Abort() oThread.Join() ' <-- Edited thx to Wile's comment below. :-) oThread = Nothing Me.lblResults.Text = "" End If End Sub Private Sub btnSuspend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSuspend.Click If Not oThread Is Nothing Then If oThread.ThreadState = Threading.ThreadState.Running Then oThread.Suspend() End If End Sub Private Sub btnResume_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResume.Click If Not oThread Is Nothing Then If oThread.ThreadState = Threading.ThreadState.Suspended Then oThread.Resume() End If End Sub end Class I have no doubt that the above approach is flawed... But baby steps, right? Hope it helps... MikevbThreadingExperiments.zip Edited February 18, 2005 by Mike_R Quote Posting Guidelines Avatar by Lebb
Wile Posted February 18, 2005 Posted February 18, 2005 Funny... I just If oThread.ThreadState = Threading.ThreadState.Suspended Then oThread.Resume() oThread.Abort() Do While oThread.ThreadState = Threading.ThreadState.Running ' Just wait. Loop oThread = Nothing A tip: don't do this in production code :p. If the thread that is aborting takes some time to abort (e.g. it has to clean up some heavy resources like bitmaps, database connection, handles, whatever), the loop will make sure the CPU is well and truely kept busy. Better would be to join the thread after the abort: oThread.Join(). This will still halt your code until the thread is finished with the abort, but it won't cause 100% cpu load ;). Quote Nothing is as illusive as 'the last bug'.
Dill Posted February 18, 2005 Posted February 18, 2005 I am trying to get multithreading working for a project. Private Sub StartClick(sender As System.Object, e As System.EventArgs) Do While i < SquareArrayList.Count ThreadControl1.Start() ThreadControl2.Start() ThreadControl3.Start() ThreadControl4.Start() Loop End Sub i believe this is your problem running the 4 threads is not a problem but when you loop you are trying to start a thread that is already running, hence the error. if you were wanting a dynamic number of threads maybe try creating a collection of threads and adding a new one when required. Public MyThreads As New ArrayList Sub main() For i As Integer = 0 To NumberofThreadsRequired AddThread() Next End Sub Private Sub AddThread() Dim MyNewThread As New Thread(AddressOf MyMethod) MyThreads.Add(MyNewThread) End Sub Private Sub MyMethod() 'Do some stuff End Sub Quote
Mike_R Posted February 18, 2005 Posted February 18, 2005 (edited) A tip: don't do this in production code... Better would be to join the thread after the abort: oThread.Join(). This will still halt your code until the thread is finished with the abort' date=' but it won't cause 100% cpu load ;).[/quote'] Thanks Wile, yeah, I was fairly hesitant to post at all given my complete lack of experience in this... I knew others would have better ways of handling this! I did notice Thread.Join(), but wasn't quite sure how it would work... Thank you for explaining it. :) [Edit: And I've now edited my code, above...] Edited February 18, 2005 by Mike_R Quote Posting Guidelines Avatar by Lebb
Diesel Posted February 18, 2005 Posted February 18, 2005 mattsrebate...Technically you are not supposed to use objects or values type defined outside the current thread (ie. i and listbox1). Instead create a class around the thread function and store the counter variable as a property. For this program I would bind an event to the thread function and raise it when it the thread is exiting, when the event is raised, restart the thread (or not depending on the condition). Quote
mattsrebatespam Posted February 18, 2005 Author Posted February 18, 2005 (edited) Multithreading out of control now i believe this is your problem running the 4 threads is not a problem but when you loop you are trying to start a thread that is already running, hence the error. if you were wanting a dynamic number of threads maybe try creating a collection of threads and adding a new one when required. I took your advice and made it dynamic. I created a thread to control the worker threads. The controller thread (ThreadController) only purpose is to spawn worker threads (ThreadWorker). The problem I am encountering now is that the number of threads is out of control. I know why (because of the loop in my code) but can't think of a way to make it behave. I also need to put a synlock in the code but I did not know how to do it. Any advice is greatly appreciated. Here is the code that is giving me the trouble: Public ThreadController As Thread Dim i As Integer = 1 Dim j As Integer = 20000 Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click ListBox.Items.Clear() StartButton.Enabled = False StopButton.Enabled = True PauseResumeButton.Enabled = True ThreadController = New Thread(AddressOf Me.ControlThreads) ThreadController.Start() End Sub Private Sub ControlThreads() Do While i < j For k As Integer = 1 To ThreadCountNumericUpDown.Value AddThread() Next Loop If i = j Then StartButton.Enabled = True StopButton.Enabled = False PauseResumeButton.Enabled = False End If End Sub Private Sub AddThread() Dim ThreadWorker As Thread = New Thread(AddressOf Me.BackgroundProcess) ThreadWorker.IsBackground = True ThreadWorker.Start() End Sub Private Sub BackgroundProcess() ListBox.Items.Add(i) i += 1 End Sub Private Sub PauseResumeButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PauseResumeButton.Click StartButton.Enabled = False StopButton.Enabled = True PauseResumeButton.Enabled = True If ThreadController.ThreadState = 64 Then ThreadController.Resume() Else ThreadController.Suspend() End If End Sub Private Sub StopButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopButton.Click StartButton.Enabled = True StopButton.Enabled = False PauseResumeButton.Enabled = False If ThreadController.ThreadState = 64 Then ThreadController.Resume() End If ThreadController.Abort() ThreadController.Join() End Sub Private Sub ExitButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitButton.Click Me.Close() End Sub MultiThreadtest.zip Edited February 19, 2005 by PlausiblyDamp Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.