-
[RESOLVED] HELP with MultiThreading
Hi, I am new in vb.Net
It is my previous problem in vb6, its hard to multithread using vb6 so I migrate my codes to vb.Net.
How can I multithread this two loops so that this process is running at the same time.
Because when I start my second Loop, my first loop stop in executing. It will start again when my 2nd loop finished.
Here is my 2 Loops:
Code:
Dim Ret As Integer
Dim i As Short
For i = 0 To ListBox1.Items.Count - 1
System.Windows.Forms.Application.DoEvents()
ListBox1.SelectedIndex = i
ListBox1.Refresh()
WriteToLog("Sending SMS to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow))
Ret = Device.SendSMS(txtDestination.Text, txtmsg.Text)
Device.GetLastError(0)
If Ret > 1 Then
WriteToLog("SMS Sent to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Lime))
End If
If Ret = -22 Then
WriteToLog("ERROR Sending to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog("ERROR: PDU error, Signal, Check Account balance.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret = -20 Then
WriteToLog("ERROR Sending to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog("ERROR: SMS Service, Check Account balance.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret = -19 Then
WriteToLog("ERROR Sending to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog("ERROR: SMSC NOT FOUND.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret = -2 Then
WriteToLog("ERROR Sending to -> " & txtDestination.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog("ERROR: PORT FAIL.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
Next
Code:
Dim Ret2 As Integer
Dim j As Short
For j = 0 To ListBox2.Items.Count - 1
System.Windows.Forms.Application.DoEvents()
ListBox2.SelectedIndex = j
ListBox2.Refresh()
WriteToLog2("Sending SMS to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow))
Ret2 = Device2.SendSMS(txtDestination2.Text, txtmsg.Text)
Device2.GetLastError(0)
If Ret2 > 1 Then
WriteToLog2("SMS Sent to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Lime))
End If
If Ret2 = -22 Then
WriteToLog2("ERROR Sending to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog2("ERROR: PDU error, Signal, Check Account balance.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret2 = -20 Then
WriteToLog2("ERROR Sending to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog2("ERROR: SMS Service, Check Account balance.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret2 = -19 Then
WriteToLog2("ERROR Sending to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog2("ERROR: SMSC NOT FOUND.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
If Ret2 = -2 Then
WriteToLog2("ERROR Sending to -> " & txtDestination2.Text, System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
WriteToLog2("ERROR: PORT FAIL.", System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
End If
Next
I have 2 connected GSM Modem in usb port.
That codes will send SMS in all contacts in my ListBox.
-
Re: HELP with MultiThreading
The two loops are very similar....and a bit strange.
At first, I saw that you were iterating through a listbox, setting the selected item with each iteration. However, I don't see that you are using the Listbox otherwise. Is the bit about setting the selected index just there to load the textbox with the text that you will actually be sending? If so, here are a couple options:
Each loop should be in a sub that will be the target of a thread. However, there is no good reason to deal with the user controls directly, and that could be problematic, so don't do it. What I would do would be to create a class that had a Thread object as a member, and took either an array of strings, or a List (of String). This could be passed in as an argument to the constructor if the class was going to send out each string in turn, and log each return value. However, if you pass the list as an argument to the constructor, that's probably less versatile. Better would be to have a public member that took the list as an argument. The class would look something like this:
Code:
Public Class Sender
private myThread as system.Threading.Thread
Public Sub New()
myThread = New system.Threading.Thread(AddressOf DoSomething)
End Sub
Public sub StartSending(sendList as List( of String))
'SOMETHING HERE.
myThread.Start
End SUb
Private Sub DoSomething()
'Most of your loop here
End Sub
End Class
That's a VERY rough outline. For one thing, passing in a list like that will actually just pass in the address of the list. I would want the class to hold a list independent to the argument passed in (so that the caller can freely alter the list that was passed in without worrying about race conditions). That would mean that the first step upon receiving a new list would be to deep copy it into a member variable. That may not be easy, as you would need to create a new list and copy each item from the old into the new.
Second, I would have a list to hold the return values (which you log as strings). The thread would add to this list, rather than logging. The list would need to be accessible via a property, such that when the thread is finished, the log can be read from the class by the UI process.
Third: How do you know when the thread is finished? For that, I would raise events, but you can't raise them from the thread, or the UI thread won't even see them. Therefore, raise the events in the UI context. My preferred implementation for that is fairly simple. I explained the use of the SynchronizationContext fairly recently, so searching on that word and my name should return a thread that I replied to with the code in it. There isn't much code, though, as it is pretty simple.
Well, those are my opening thoughts.
-
Re: HELP with MultiThreading
try this:
vb Code:
Dim thread1 As New Threading.Thread(AddressOf runLoop1)
thread1.Start()
Dim thread2 As New Threading.Thread(AddressOf runLoop2)
thread2.Start()
Private Sub runLoop1()
'put loop 1 here
End Sub
Private Sub runLoop2()
'put loop 2 here
End Sub
-
Re: HELP with MultiThreading
Hi, I tried paul example but got some error:
Code:
System.InvalidOperationException was unhandled
Message="Cross-thread operation not valid: Control 'ListBox1' accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.Control.SendMessage(Int32 msg, Int32 wparam, Int32 lparam) at System.Windows.Forms.ListBox.get_SelectedIndex() at System.Windows.Forms.ListBox.set_SelectedIndex(Int32 value) at multithreading.frmMain.Device1() in J:\Aktif VB.net\multithreading\frmMain.vb:line 12 at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
InnerException:
the error occur and point me.
vb Code:
ListBox1.SelectedIndex = i
-
Re: HELP with MultiThreading
That's because you have to invoke the ListBox since it's going to be used in another thread. This thread might help you learn how to invoke.
Hope it helps ;)
-
Re: HELP with MultiThreading
Given that there seems to be so much accessing of controls it is not going to be feasible to continue doing things the way you currently are. You'll be context-switching between threads so much that you may even find that your app runs slower. I think you're going to restructure your code somewhat. The first step in that is to actually explain what it is you're trying to achieve, in an overall sense. That should pretty much be the first step in every new post.
-
Re: HELP with MultiThreading
jmcilhinney, couple of questions regarding multithreading:
If one were to access the list box to complete two actions at the same time, instead of multithreading, couldn't one use two background workers? Does it depends on what I'm trying to achieve?
I'm aware that using BGW means writing more lines of code...
Thanks ;)
EDIT:
I've come to my conclusion, both complete an action on a different thread, however the BGW can report the action and can be cancelled. Those are the only difference between them, right?
-
Re: HELP with MultiThreading
Quote:
Originally Posted by
tassa
jmcilhinney, couple of questions regarding multithreading:
If one were to access the list box to complete two actions at the SAME TIME, instead of multithreading, couldn't one use two background workers? Or is multithreading better? Does it depends on what I'm trying to achieve?
I'm aware that using BGW means writing more lines of code...
Thanks ;)
The BackgroundWorker is not an alternative to multi-threading. It's just a simpler way to implement multi-threading. The main point of the BackgroundWorker is that you can execute an action on a background thread without having to explicitly create a Thread object and you can also pass data back to the UI thread without having to use delegation. The DoWork event of a BackgroundWorker is raised on a thread pool thread, while the ProgressChanged and RunWorkerCompleted events are raised on the UI thread.
-
Re: HELP with MultiThreading
-
Re: HELP with MultiThreading
Hi, I reconstructed my codes to this, But still my first device paused in sending sms when my 2nd device start sending sms too.
here is my new codes with threading, maybe im doing wrong with threading..
Code:
Dim SendSMS1 As System.Threading.Thread
Dim SendSMS2 As System.Threading.Thread
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SendSMS1 = New System.Threading.Thread(AddressOf Device1) ' Call sub procedure "Device1"
SendSMS1.Start() ' start thread
End Sub
Private Sub Device1()
Dim Ret As Integer
Dim i As Integer
For i = 0 To ListBox1.Items.Count - 1
Ret = Device.SendSMS(ListBox1.Items.Item(i), txtmsg.Text)
Device.GetLastError(0)
Next
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
SendSMS2 = New System.Threading.Thread(AddressOf Device12) ' Call sub procedure "Device12"
SendSMS2.Start() ' start thread
End Sub
Private Sub Device12() '(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Dim Ret2 As Integer
Dim j As Integer
For j = 0 To ListBox2.Items.Count - 1
Ret2 = Device2.SendSMS(ListBox2.Items.Item(j), txtmsg.Text)
Device2.GetLastError(0)
Next
End Sub
What I want to achive with this is; this 2 Device will send an SMS at the same time, (simultaneously)
-
Re: HELP with MultiThreading
bump for my post...
Anyone can?
-
Re: HELP with MultiThreading
I'm just guessing here, but I think that if you call both threads from the orginal thread (is it still clear?), you're attempting to complete two actions on the same thread, for this the first one that was created has to wait until the second one finishes... I think that's the issue... Why not put one thread inside the other or have two background workers, since it simplefies multithreading...
Just an idea ;)
-
Re: HELP with MultiThreading
Quote:
Originally Posted by
tassa
you're attempting to complete two actions on the same thread, for this the first one that was created has to wait until the second one finishes... I think that's the issue...
yup and that is my problem..
-
Re: HELP with MultiThreading
The code as you have it is correctly spawning two new worker threads, though I would not bother explicitly creating them. Instead, I would suggest ThreadPool.QueueUserWorkItem().
-
Re: HELP with MultiThreading
Hey, someone told me that instead of using For Loop function, I need to use Timer..
Hm mm....but how can I use a timer to loop the numbers in my List Box and send SMS?
And no need to use multithreading and my issue will be resolve.
Anyone can help me regarding that, I'm new in vb.net..
-
Re: HELP with MultiThreading
The code looks correct. How are "Device2" and "Device" declared? Also, could this be a hardware issue? You said in your first post that you are sending info to the USB ports, are you sure that section of the code is correct?
-
Re: HELP with MultiThreading
Quote:
Originally Posted by
ProphetBeal
The code looks correct. How are "Device2" and "Device" declared? Also, could this be a hardware issue? You said in your first post that you are sending info to the USB ports, are you sure that section of the code is correct?
that 2 device are GSM Modem connected to usb port.
the issue is it cant send SMS at the same time. coz when two loops are running one modem got stop in sending sms..and will continue sending when other modem finished the loop.
-
Re: HELP with MultiThreading
If you have to wait for the second action to be completed in order to complete the first one, won't ThreadPool.QueueUserWorkItem() resolve your problem?
-
Re: HELP with MultiThreading
I stand by the design I was suggesting earlier, but I don't think it will work any better than what you are doing now. I would guess that the device only allows a single process to interact with it at one time, so starting the second thread blocks the first until it has completed. I can think of a solution to that (both threads add requests to a queue, while a third thread pumps the queue through the device) , but I can't think of a GOOD solution to that.
-
Re: HELP with MultiThreading
Quote:
Originally Posted by
Shaggy Hiker
I would guess that the device only allows a single process to interact with it at one time, so starting the second thread blocks the first until it has completed..
But I am using 2 separate device. connected to 2 usb ports.
-
Re: HELP with MultiThreading
2 separate devices, connected to 2 usb ports + 2 seperate threads shouldn't block each other
-
Re: HELP with MultiThreading
maybe the fault is coming from my active X that used.....
maybe i need to study SerialPort in vb.Net and use AT Commands, instead of using active x.
If i use SerialPort and AT commands, is my problem will be solve?
-
Re: HELP with MultiThreading
I agree, I had overlooked that.
So it looks pretty good. What is Device? Is it a class that you wrote, or something else? How do you create the two device instances?
Basically, what you have shown us looks reasonable, and I have a highly unreasonable suspicion about the device object, but Sherlock Holmes once said "When you rule out the probable, whatever is left, no matter how improbable, is the truth." Unfortunately, this is not really what is left, but it IS the easiest thing to investigate.
-
Re: HELP with MultiThreading
anyone can try to convert my codes to use Timer.
-
Re: HELP with MultiThreading
The timer solution would be worse than what you have now, even if you are not really getting threading. After all, the only way that I can see to use a timer would be to send out one message on every timer tick. Since the minimum timer tick isn't all that fast, you would be effectively single-threading your app, but in an especially slow way.
-
Re: HELP with MultiThreading
Besides, even if you add a timer to the code, it would try to send a msg every, let's say 100ms, however it would still have to w8 for the first one to be sent, so it's relatively slower(100ms doesn't seem like much, but try sending 1000 with a timer, it'll take longer...).
I would stick to your actual code...
In other words I agree with Shaggy Hiker...
-
Re: HELP with MultiThreading
Quote:
Originally Posted by
Shaggy Hiker
but Sherlock Holmes once said "When you rule out the probable, whatever is left, no matter how improbable, is the truth."
It's..."When you have eliminated the impossible, whatever remains, however improbable, must be the truth."
You still have yet to tell us what "Device" and "Device2" are. How are they instantiated?
-
Re: HELP with MultiThreading
Device and Device2 are active X that communicate and interact with my 2 GSM modems.
BTW, this problem can be considered resolved now.
I used timer instead of For Loop.