-
5 Attachment(s)
[RESOLVED] Sleep() not sleeping for some reason
I have created a test application to test my multithreading by creating threads which put the numbers 1 to 100 in columns of an excel spreadsheet. I use a form1 button click to start the threads. One thread starts and then, after 2 seconds the next thread starts so I can see all the threads running at the same time
Code:
01 Public Class Form1
02
03 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
04 Dim testthread As New System.Threading.Thread(AddressOf Module1.loop3)
05 Dim testthread1 As New System.Threading.Thread(AddressOf Module1.loop3)
06 Dim testthread2 As New System.Threading.Thread(AddressOf Module1.loop3)
07 Dim testthread3 As New System.Threading.Thread(AddressOf Module1.loop3)
08 Dim testthread4 As New System.Threading.Thread(AddressOf Module1.loop3)
09 testthread.Start(1)
10 System.Threading.Thread.Sleep(2000)
11
12 testthread1.Start(2)
13 System.Threading.Thread.Sleep(2000)
14 testthread2.Start(3)
15 System.Threading.Thread.Sleep(2000)
16 testthread3.Start(4)
17 System.Threading.Thread.Sleep(2000)
18 testthread4.Start(5)
19 System.Threading.Thread.Sleep(2000)
20 Call Module1.loop3(6)
21 End Sub
22 End Class
01 Public Module Module1
02 Dim xl = CreateObject("excel.application")
03 Delegate Sub testo()
04
05
06
07
08 Public Sub loop3(ByVal column As Integer)
09
13 If xl.visible <> True Then
14 xl.visible = True
15 End If
19 Try
20 If Not xl.activeworkbook.name = "Spenddown IN Mdcd.xlsm" Then
21 xl.workbooks.open("C:\Documents and Settings\BMcGuir1\Desktop\Test\spenddown in mdcd.xlsm")
22 GoTo done
23 End If
24
25 Catch
26 xl.workbooks.open("C:\Documents and Settings\BMcGuir1\Desktop\Test\spenddown in mdcd.xlsm")
27 End Try
28
29 done:
36 Dim y As Long
37 For y = 1 To 100
38 xl.activeworkbook.sheets("sheet1").cells(y, column).value = y
39 System.Threading.Thread.Sleep(100)
40 Next
41 'MsgBox("done")
42 End Sub
43
44 End Module
I have this EXACT same code on form2 on another project and the sleeps between the thread starts don't work. When I run it on another project all 6 threads start after the buttonclick event is over. when 6 threads try to open an excel spreadsheet at the same time problems start. Why is sleep() working on one application but not another? Any help is appreciated. I tried to attach the project in which sleep is not working but the server returned an error during upload. I've attached the application to this post. I've also researched to try to find out why sleep() would not work and I have not found anything.
-
Re: Sleep() not sleeping for some reason
Hi, if it works in one project and not another then the problem would lie in code somewhere. Have you imported the system.threading? also wouldnt you need to tell it which thread to sleep? as in
Code:
testthread2.Sleep(2000)
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
bensonsearch
Hi, if it works in one project and not another then the problem would lie in code somewhere. Have you imported the system.threading? also wouldnt you need to tell it which thread to sleep? as in
Code:
testthread2.Sleep(2000)
i'm not wanting to sleep testthread2. I'm wanting to start a thread, sleep for 2 seconds, start a thread, sleep for 2 seconds, start a thread. I attached the project to my post so you can see the code.
-
Re: Sleep() not sleeping for some reason
If you are talking about Button 5 the sleep is 20 seconds.
-
Re: Sleep() not sleeping for some reason
If this is just an exercise in testing out Sleep, why deal with Excel at all? If this isn't just an exercise in testing sleep....well, then there are plenty of oddities to that code. The most basic question, though, is this: How do you know that it is not sleeping? You just say that all six threads start after the click event. That doesn't sound like the sleep isn't happening, that sounds like you are expecting something to happen with the threads IMMEDIATELY, before the sleep happens. There's no reason to expect that. All those threads work on their own speed, and that will be dependent on other factors that you have little or no control over.
Frankly, if you are having trouble with working with Excel in multiple threads, then why are you working with Excel in multiple threads in the first place? The design makes no sense, as written, but it certainly sounds like it is working based on what description you gave.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
If this is just an exercise in testing out Sleep, why deal with Excel at all? If this isn't just an exercise in testing sleep....well, then there are plenty of oddities to that code. The most basic question, though, is this: How do you know that it is not sleeping? You just say that all six threads start after the click event. That doesn't sound like the sleep isn't happening, that sounds like you are expecting something to happen with the threads IMMEDIATELY, before the sleep happens. There's no reason to expect that. All those threads work on their own speed, and that will be dependent on other factors that you have little or no control over.
Frankly, if you are having trouble with working with Excel in multiple threads, then why are you working with Excel in multiple threads in the first place? The design makes no sense, as written, but it certainly sounds like it is working based on what description you gave.
My questions is this:
When I run this code on this application that i've attached:
All 6 threads start at the exact same time.
When I run this code on another application:
Thread one starts, and then after 2 seconds thread 2 starts, then after two seconds thread 3 starts, then after two seconds thread 4 starts.
How come, on this application, all the threads start at the same time while on another application the sleep() causes there to be a 2 second delay between threads starting? I know that it's not sleeping because when I run this EXACT code on another application the sleep(2000) is causing there to be a 2 second delay in the thread starts
-
Re: Sleep() not sleeping for some reason
How do you know when the thread starts? What means are you using to determine that?
EDIT: The reason I ask this is that you seem to be wanting multi-threading to act in a way that it does not. Once you start a thread, you have no control over WHEN it gets to ANY particular statement. That comes down to how the OS deals with threads, and it can vary in all kinds of different ways. You are starting a thread, then sleeping the main thread. If you could say "This other thread will accomplish X amount of work during these two seconds." then you would be asserting how far a thread must get during some segment of time, which you can't safely do under any circumstance. Therefore, even wanting this is dangerous, because you might come to rely on a measure you can't guarantee. The very same code that worked on one system at one time might not work on a different system, or the same system at a different time. You'd have a race condition, which is the nastiest possible bug because failure would be unpredictable and intermittent.
-
Re: Sleep() not sleeping for some reason
So I did a test. In form1 I have this
Code:
Dim f As New Form2
f.Show()
Here is form2
Code:
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim stpw As New Stopwatch
stpw.Restart()
Threading.Thread.Sleep(2000)
stpw.Stop()
Debug.WriteLine(stpw.Elapsed.ToString)
stpw.Restart()
Threading.Thread.Sleep(2000)
stpw.Stop()
Debug.WriteLine(stpw.Elapsed.ToString)
stpw.Restart()
Threading.Thread.Sleep(2000)
stpw.Stop()
Debug.WriteLine(stpw.Elapsed.ToString)
End Sub
Form2 slept for 2 seconds each time.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
How do you know when the thread starts? What means are you using to determine that?
EDIT: The reason I ask this is that you seem to be wanting multi-threading to act in a way that it does not. Once you start a thread, you have no control over WHEN it gets to ANY particular statement. That comes down to how the OS deals with threads, and it can vary in all kinds of different ways. You are starting a thread, then sleeping the main thread. If you could say "This other thread will accomplish X amount of work during these two seconds." then you would be asserting how far a thread must get during some segment of time, which you can't safely do under any circumstance. Therefore, even wanting this is dangerous, because you might come to rely on a measure you can't guarantee. The very same code that worked on one system at one time might not work on a different system, or the same system at a different time. You'd have a race condition, which is the nastiest possible bug because failure would be unpredictable and intermittent.
I know when the thread starts because I can see the numbers being put on the column of an excel spreadsheet. Thread 1 is column 1, thread 2 is column 2, thread 3 is columng 3 etc.
I run this on one app and I see the spreadsheet and I can visibily see thread 1 start putting numbers on column 1 and then, after 2 seconds, thread 2 start putting numbers into column 2 and then, after 2 seconds thread 3 starts putting numbers into column 3.
I run this on the app that i've linked here and when I press the button all 6 columns are getting numbers at the same time. There is no delay between one column and another
I put the whole project here.
http://www.yourfilelink.com/get.php?fid=831569
-
Re: Sleep() not sleeping for some reason
[QUOTE=dbasnett;4332341]So I did a test. In form1 I have this
Code:
Dim f As New Form2
f.Show()
how would it affect my code if I just had form2.show() instead of dimming f as new form2 and f.show()? On my code I just have form2.show() although i tried showing my form2 like this and sleep() still didn't sleep.
-
Re: Sleep() not sleeping for some reason
That could be the issue, or part of it. You are using the default instance. Normally, objects are not thread specific, but default instances work in a different fashion that can have some suprising implications. It doesn't seem to me that the use of the default instance should cause the behavior you are seeing, but what you have described is some entanglements of one sort or another. I wouldn't expect that the thread affinity of the default instance would translate into thread affinity for the other threads, but I don't know how MS implemented the thing.
The easiest solution, since it is a good idea in pretty nearly EVERY case, is to try not using the default instance. The reason I dislike the default instance isn't because of thread affinity, but because it causes horrendous confusion without providing any real benefits to most people.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
That could be the issue, or part of it. You are using the default instance. Normally, objects are not thread specific, but default instances work in a different fashion that can have some suprising implications. It doesn't seem to me that the use of the default instance should cause the behavior you are seeing, but what you have described is some entanglements of one sort or another. I wouldn't expect that the thread affinity of the default instance would translate into thread affinity for the other threads, but I don't know how MS implemented the thing.
The easiest solution, since it is a good idea in pretty nearly EVERY case, is to try not using the default instance. The reason I dislike the default instance isn't because of thread affinity, but because it causes horrendous confusion without providing any real benefits to most people.
I tried dim frm2 as new form2 and I also tried to make dim f2 as new form2 outside of the sub as a class level variable and they both still had the same problem
-
Re: Sleep() not sleeping for some reason
That's good, frankly. I was having a hard time figuring out how the thread affinity of the default instance could impact threads spawned by the object.
So, is this a correct explanation of what you expect:
Numbers come from thread 1.
Wait 2 seconds.
Numbers come from thread 2.
Wait 2 seconds.
Numbers come from thread 3.
And what you are actually seeing is:
Wait 6 seconds.
Numbers come from threads 1, 2, and 3
Or is what you are seeing more like this:
Wait 6 seconds
Numbers come from thread 1
Numbers come from thread 2
Numbers come from thread 3
If either of those two are the way you are seeing this behave, then the first thing I would do would be to extend the wait time from 2 seconds to 10 seconds. If the delay then went from 6 seconds to 30 seconds (a difference that would be VERY obvious, which was all I was looking for), then that would suggest one issue, but if the delay didn't go to 30 seconds, that would suggest a different issue. Aside from that, the other question is whether the three threads, when they do run, run simultaneously or run sequentially?
-
Re: Sleep() not sleeping for some reason
I also noticed that you are using DoEvents, though I don't think it is the problem, but it is something to look at. I have never had or seen an actual failure of sleeping a thread.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
That's good, frankly. I was having a hard time figuring out how the thread affinity of the default instance could impact threads spawned by the object.
So, is this a correct explanation of what you expect:
Numbers come from thread 1.
Wait 2 seconds.
Numbers come from thread 2.
Wait 2 seconds.
Numbers come from thread 3.
And what you are actually seeing is:
Wait 6 seconds.
Numbers come from threads 1, 2, and 3
This is what I'm seeing
Quote:
If either of those two are the way you are seeing this behave, then the first thing I would do would be to extend the wait time from 2 seconds to 10 seconds. If the delay then went from 6 seconds to 30 seconds (a difference that would be VERY obvious, which was all I was looking for), then that would suggest one issue, but if the delay didn't go to 30 seconds, that would suggest a different issue. Aside from that, the other question is whether the three threads, when they do run, run simultaneously or run sequentially?
If I try this
Numbers come from thread 1.
Wait 20 seconds.
Numbers come from thread 2.
Wait 20 seconds.
Numbers come from thread 3.
wait 20 seconds.
I wait 60 seconds and then everything starts at once whereas I do that same thing on another app and the sleeps actually sleep.
-
Re: Sleep() not sleeping for some reason
Ok, that's good information. The three threads are being queued up, but are not actually starting until after the UI thread is done sleeping. So, something blocks execution until released by the UI thread. Once that block is removed, all three threads run simultaneously, which means that the results will come out in any order. Had they been sequential, then there would have been some other kind of block that was allowing each thread to own a region in turn. The situation you have found is simpler, but it still isn't easy to solve.
What is causing the block? That I can't say. There is something different between the app that works and the app that doesn't work, and this difference could be nearly anything. For one thing, I have been assuming that both apps are on the same computer, so you aren't seeing a hardware difference. That leaves the module, itself, as the most likely culprit. After all, the threads all work with some non-thread local variables, such as the Excel object. From your description, the UI thread is locking on the object, then releasing the lock at the end of the button sub. Why it would do that, I can't say based on what you are showing, and the lock could actually be elsewhere. However, a few things can be tested:
Put breakpoints on these two lines:
In the module:
If xl.visible <> True Then
In the click event:
End Sub
Which breakpoint is hit first? If you get to the module breakpoint right away, then the Excel object is where the lock is being held, and that may well be something internal to Excel. If you get to the End Sub breakpoint first, then the Start call on the threads is not occuring until after the click event completes. That would be rather odd, because it's a bit hard to see where the block would be held that would prevent the setting up of the threads themselves. The threads are probably being pooled, so it would be acting like the thread scheduler was held by the UI thread for the duration of the button click. That would be rather odd.
The ultimate key is to figure out what the difference is between the app where it works and the app where it does not. The test I proposed would really do no more than narrow down what to look at. If the code you posted is complete for those methods, then the problem is occuring in code that you didn't show. Are you using threading elsewhere? Are you locking any objects explicitly?
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
Ok, that's good information. The three threads are being queued up, but are not actually starting until after the UI thread is done sleeping. So, something blocks execution until released by the UI thread. Once that block is removed, all three threads run simultaneously, which means that the results will come out in any order. Had they been sequential, then there would have been some other kind of block that was allowing each thread to own a region in turn. The situation you have found is simpler, but it still isn't easy to solve.
What is causing the block? That I can't say. There is something different between the app that works and the app that doesn't work, and this difference could be nearly anything. For one thing, I have been assuming that both apps are on the same computer, so you aren't seeing a hardware difference. That leaves the module, itself, as the most likely culprit. After all, the threads all work with some non-thread local variables, such as the Excel object. From your description, the UI thread is locking on the object, then releasing the lock at the end of the button sub. Why it would do that, I can't say based on what you are showing, and the lock could actually be elsewhere. However, a few things can be tested:
Put breakpoints on these two lines:
In the module:
If xl.visible <> True Then
In the click event:
End Sub
Which breakpoint is hit first? If you get to the module breakpoint right away, then the Excel object is where the lock is being held, and that may well be something internal to Excel. If you get to the End Sub breakpoint first, then the Start call on the threads is not occuring until after the click event completes. That would be rather odd, because it's a bit hard to see where the block would be held that would prevent the setting up of the threads themselves. The threads are probably being pooled, so it would be acting like the thread scheduler was held by the UI thread for the duration of the button click. That would be rather odd.
The ultimate key is to figure out what the difference is between the app where it works and the app where it does not. The test I proposed would really do no more than narrow down what to look at. If the code you posted is complete for those methods, then the problem is occuring in code that you didn't show. Are you using threading elsewhere? Are you locking any objects explicitly?
The If xl.visible <> True breakpoint is hitting first.
I'm not locking objects on either application. On the application where sleep() is not working on form1 I have Inherits System.Windows.Forms.Form. If I remove that inherits it has no effect on my sleep() problem.
-
Re: Sleep() not sleeping for some reason
You may not be locking, but SOMETHING sure is. If that breakpoint is hitting first then the threads actually ARE starting as you expect. The sleep is happening just as you would expect it to. The issue is that the output is not coming out as you expected, and that may be quite a bit harder to diagnose.
I'm not sure that it would be useful, but my next step would be to move the breakpoint further and further down that method to see how far into the method the thread gets before it blocks. I would guess that it blocks immediately, and that if you were to move the breakpoint down to this line:
If Not xl.activeworkbook.name = "Spenddown IN Mdcd.xlsm" Then
it would finish the button click (and hit the End Sub breakpoint) before hitting the breakpoint in the method. That would mean that the Excel app itself has been locked by the UI thread prior to any of the threads starting. However, it may be that you can move the breakpoint as far as this line:
xl.activeworkbook.sheets("sheet1").cells(y, column).value = y
in which case it is probably the workbook itself that is restricting access. Figuring that out may not help any, though.
That Inherits line isn't necessary. If it was necessary, the program wouldn't even have compiled when you removed it, because the app would no longer recognize ANY forms. Since removing it didn't stop the program from running entirely, then it isn't needed because the objects named are otherwise available.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
You may not be locking, but SOMETHING sure is. If that breakpoint is hitting first then the threads actually ARE starting as you expect. The sleep is happening just as you would expect it to. The issue is that the output is not coming out as you expected, and that may be quite a bit harder to diagnose.
I'm not sure that it would be useful, but my next step would be to move the breakpoint further and further down that method to see how far into the method the thread gets before it blocks. I would guess that it blocks immediately, and that if you were to move the breakpoint down to this line:
If Not xl.activeworkbook.name = "Spenddown IN Mdcd.xlsm" Then
it would finish the button click (and hit the End Sub breakpoint) before hitting the breakpoint in the method. That would mean that the Excel app itself has been locked by the UI thread prior to any of the threads starting. However, it may be that you can move the breakpoint as far as this line:
xl.activeworkbook.sheets("sheet1").cells(y, column).value = y
in which case it is probably the workbook itself that is restricting access. Figuring that out may not help any, though.
That Inherits line isn't necessary. If it was necessary, the program wouldn't even have compiled when you removed it, because the app would no longer recognize ANY forms. Since removing it didn't stop the program from running entirely, then it isn't needed because the objects named are otherwise available.
When I move the breakpoint after making xl.visible I can see that the excel workbook is being made visible before the button click event ends.
I added a debug.print of the column variable which is being passed when the thread starts before it hits the breakpoint and thread 1 starts first, thread 6 starts second and thread 3 starts third. If there is a sleep(10,000) between starting the threads then shouldn't thread 1 hit first and thread 2 hit second?
I added debug prints to show what thread hits what part of the loop first. Why is it that the first thread is getting past making excel visible 50 seconds after the 5th thread is?
before visible 1
before visible 2
before visible 3
before visible 4
before visible 5
before visible 6
after visible 5
after visible 6
after visible 1
after visible 3
after visible 2
after visible 4
When all the threads are putting information on the spreadsheet at the same time I get and error "The object invoked has disconnected from its clients"
When I run the same thing on another app this is what happens:
before visible 1
after visible 1
after open 1
before visible 2
after visible 2
after open 2
before visible 3
after visible 3
after open 3
before visible 4
after visible 4
after open 4
before visible 5
after visible 5
after open 5
before visible 6
after visible 6
after open 6
Is there some setting or something on one app which is causing the threads to go out of order?
-
Re: Sleep() not sleeping for some reason
There is no guarantee of the order in the threads. That's entirely up to whim, as far as you are concerned. There are lots of factors that are involved, and you may well be able to identify some of them, but ultimately: The order of execution of threads can't be definitively determined.
That may be the whole issue. Why it's happening right on one and not on the other may be pure coincidence. The one thing you can say for certain is this: If you care about the order of execution of threads, then you have to force them to that order (generally by not using threads). You can't ever count on threads to run in any particular order or else you are just asking for trouble. Having the proper execution of an app depend on the order of execution of a series of concurrent threads is a race condition, which is pretty much always a bug. Thread scheduling is up to the OS. There are rules as to how threads will be added, how they will get time allocated to them, and so on. You can't change that in any good way (you can change it in a really BAD way by fiddling with priority levels, but don't do that).
Having said that, due to the amount of time that you are sleeping the threads, the pattern you are seeing is probably due to things other than race conditions, alone. There is a chokepoint somewhere in the code that is controlling passage for some critical section of the code. This could be in Excel, or it could be elsewhere. You may or may not be able to figure it out, but even if you did figure it out you would be well advised not to really rely on the order of execution for threads. If the order is necessary, get rid of the threads and make them operate in the order you need.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
There is no guarantee of the order in the threads. That's entirely up to whim, as far as you are concerned. There are lots of factors that are involved, and you may well be able to identify some of them, but ultimately: The order of execution of threads can't be definitively determined.
That may be the whole issue. Why it's happening right on one and not on the other may be pure coincidence. The one thing you can say for certain is this: If you care about the order of execution of threads, then you have to force them to that order (generally by not using threads). You can't ever count on threads to run in any particular order or else you are just asking for trouble. Having the proper execution of an app depend on the order of execution of a series of concurrent threads is a race condition, which is pretty much always a bug. Thread scheduling is up to the OS. There are rules as to how threads will be added, how they will get time allocated to them, and so on. You can't change that in any good way (you can change it in a really BAD way by fiddling with priority levels, but don't do that).
Having said that, due to the amount of time that you are sleeping the threads, the pattern you are seeing is probably due to things other than race conditions, alone. There is a chokepoint somewhere in the code that is controlling passage for some critical section of the code. This could be in Excel, or it could be elsewhere. You may or may not be able to figure it out, but even if you did figure it out you would be well advised not to really rely on the order of execution for threads. If the order is necessary, get rid of the threads and make them operate in the order you need.
how can I do multiple things at the simeltaneously (like filling in columns on a spreadsheet) if i'm not using multiple threads? If the order of execution of threads can't be determined then how come i'm able to determine the execution of threads when I run this same code on another application. The thread that I start first executes first and the thread that I start second executes second etc...
Also if I start a thread that takes 10 seconds to run and then sleep() after starting that thread for 20 seconds shouldn't that thread be complete after the sleep? Why is it on here that when I sleep for 20 seconds after starting a 10 second thread and the 10 second thread has yet to anything other than a debug.print after 20 seconds?
-
Re: Sleep() not sleeping for some reason
In what world do spreadsheet columns get filled in simultaneously? A better way to ensure that the spreadsheet program crashes I cannot imagine!
As has been stated, you are not in control of the execution order of multiple threads. Even if everything works the way you want it to you only think that you are in control because of the coincidence. Once you have it firmly established that you are not in control your final question answers itself. You are not in control. You cannot get control. Multiple threads will ultimately do whatever they like!
-
Re: Sleep() not sleeping for some reason
I also agree with the general idea that if order or execution is essential to your purpose then you really should not be using threads.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
dunfiddlin
In what world do spreadsheet columns get filled in simultaneously? A better way to ensure that the spreadsheet program crashes I cannot imagine!
I have posted the code in which spreadsheet columns are filled simultaneously without crashing the spreadsheet program on this thread.
Quote:
Originally Posted by
dunfiddlin
As has been stated, you are not in control of the execution order of multiple threads. Even if everything works the way you want it to you only think that you are in control because of the coincidence. Once you have it firmly established that you are not in control your final question answers itself. You are not in control. You cannot get control. Multiple threads will ultimately do whatever they like!
If that is true then why is it, using the code posted on this forum in a different application, I can start a 10 second thread and sleep() for 20 seconds and see that the 10 second thread I just started is done after 10 seconds during the sleep()?
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
I also agree with the general idea that if order or execution is essential to your purpose then you really should not be using threads.
This forum post is not about controlling the order of execution of my threads. It's about understanding why sleep() works fine with the same code, same computer, different application then on this appliction appears to be not working.
-
Re: Sleep() not sleeping for some reason
Thread execution order is inherently unpredictable which is about the best answer for your question. Your observation about threads all executing after all the sleeps is extreme but not surprising to me given the way threads work in Windows.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
Thread execution order is inherently unpredictable which is about the best answer for your question. Your observation about threads all executing after all the sleeps is extreme but not surprising to me given the way threads work in Windows.
I've stumped everyone! lol
-
Re: Sleep() not sleeping for some reason
Actually you have your answer. There is no guarantee that when you call a Thread object's Start method that the thread would begin immediately. That's what everyone including me is saying. That thread will start anytime the OS is ready to start it which is something we cannot predict hence why thread execution order is unpredictable.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
Actually you have your answer. There is no guarantee that when you call a Thread object's Start method that the thread would begin immediately. That's what everyone including me is saying. That thread will start anytime the OS is ready to start it which is something we cannot predict hence why thread execution order is unpredictable.
Code:
Public Sub testthis(ByVal thread As String)
MsgBox(thread.ToString)
End Sub
Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
Dim testthread As New System.Threading.Thread(AddressOf testthis)
Dim testthread1 As New System.Threading.Thread(AddressOf testthis)
Dim testthread2 As New System.Threading.Thread(AddressOf testthis)
Dim testthread3 As New System.Threading.Thread(AddressOf testthis)
Dim testthread4 As New System.Threading.Thread(AddressOf testthis)
testthread.Start(1)
System.Threading.Thread.Sleep(1500)
testthread1.Start(2)
System.Threading.Thread.Sleep(1500)
testthread2.Start(3)
System.Threading.Thread.Sleep(1500)
testthread3.Start(4)
System.Threading.Thread.Sleep(1500)
testthread4.Start(5)
System.Threading.Thread.Sleep(1500)
Call testthis(6)
End Sub
I don't understand how thread execution order is unpredictable when I can look at the code, predict the order the msgbox numbers will show and see, plain as day, that i've accurately predicted the execution order of my threads. Are you honestly telling me that, when I run threads like this, It's not uncommon to have them show up in some random order when I've yet to see these message boxes show up out of order or anything more than about 1.5 seconds apart?
-
Re: Sleep() not sleeping for some reason
I don't know about common but its not surprising either. In your original code you're calling on excel objects. Who knows what those calls are doing internally. If for whatever reason they are blocking at any point for any amount of time, it can appear as if the threads haven't begun executing. Maybe excel has its own threading magic going on that is delaying your threads. We really don't know but what is important is that you realize that you have no guarantees about when threads start or switch or how long they execute before they switch which is the only possible explanation for your observations.
If you really want to press this then I suggest you use a more ridiculous time in your original excel code. Use something like 10 seconds for your sleep, observe and tell us what happened. That may yield some clue.
-
Re: Sleep() not sleeping for some reason
Also, I noticed in your original code that you're calling that loop3 method multiple times on different threads yet inside the method, it refers to a field at the class/module level. I'd greatly advise you synchronize access to that field via SyncLock. For all we know, that could also cause your problem.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
iamcpc
I don't understand how thread execution order is unpredictable when I can look at the code, predict the order the msgbox numbers will show and see, plain as day, that i've accurately predicted the execution order of my threads. Are you honestly telling me that, when I run threads like this, It's not uncommon to have them show up in some random order when I've yet to see these message boxes show up out of order or anything more than about 1.5 seconds apart?
Yes, we are honestly saying that very thing. Would you like to read a good book on the subject? It is pretty large, but goes into great detail about what is happening in threading under different models. One of the points that you would get from it would be that the actual behavior is different on different versions of Windows. Another point would be that the behavior will be different with a different number of cores in the CPU, but the same OS. A third point would be that the total number of threads (not just in your app, but elsewhere) will change the behavior and can do so in entirely unpredictable ways. For example, the number of threads started will be based on an OS estimation of the number of threads in current use. That estimate could be wrong because there is some OS thread operating that ends soon after the estimation is made, thereby reducing the total thread load on the system, but the OS will then spin up extra threads to optimize the CPU load. However, if one or more threads is active, but is simply blocking (perhaps because of a call to Sleep that causes the thread to pass up its execution window), then the OS will spin up yet more threads, which may cause a problem because the sleeping thread could then wake up, thereby causing some thread (good luck predicting which one) to starve for time until another one completes.
I do think that you are doing something in one of those apps that you are not doing in the other, and that extra thing is partially causing the behavior you are seeing, since you have determined that all the threads are actually starting as expected, but are completing based on what looks like some kind of locking behavior. However, what you are doing is inherently unpredictable, so the fact that it works consistently in one of those apps is nothing but pure chance (and woefully inefficient, at that, since you had to push the sleep times up to get the behavior you are seeing).
Ultimately, you are doing two things wrong:
1) You have an expectation for how threads work that is not based on a sound understanding of what they do. The book I would recommend would fix that, but it's neither small nor light in content.
2) You are using threads in a way that inherently relies on a race condition always coming out the same way. That's a dangerous design, because, even if you got it to work, it would only work most of the time, and the more different the conditions it ran in, the less likely it would be to work the way you expected.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
Also, I noticed in your original code that you're calling that loop3 method multiple times on different threads yet inside the method, it refers to a field at the class/module level. I'd greatly advise you synchronize access to that field via SyncLock. For all we know, that could also cause your problem.
But if the OP did that, they might as well throw out the threading in the first place, as they would end up creating an execution train proceeding through the method as if it really was single threaded, so the multithreading would be slower than a single threaded solution. On the other hand, switching to single threading is probably the thing to do anyways.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
Yes, we are honestly saying that very thing. Would you like to read a good book on the subject? It is pretty large, but goes into great detail about what is happening in threading under different models. One of the points that you would get from it would be that the actual behavior is different on different versions of Windows. Another point would be that the behavior will be different with a different number of cores in the CPU, but the same OS. A third point would be that the total number of threads (not just in your app, but elsewhere) will change the behavior and can do so in entirely unpredictable ways. For example, the number of threads started will be based on an OS estimation of the number of threads in current use. That estimate could be wrong because there is some OS thread operating that ends soon after the estimation is made, thereby reducing the total thread load on the system, but the OS will then spin up extra threads to optimize the CPU load. However, if one or more threads is active, but is simply blocking (perhaps because of a call to Sleep that causes the thread to pass up its execution window), then the OS will spin up yet more threads, which may cause a problem because the sleeping thread could then wake up, thereby causing some thread (good luck predicting which one) to starve for time until another one completes.
We are talking about two apps running on the same computer with the same OS, same everything.
Quote:
Originally Posted by
Shaggy Hiker
I do think that you are doing something in one of those apps that you are not doing in the other, and that extra thing is partially causing the behavior you are seeing, since you have determined that all the threads are actually starting as expected, but are completing based on what looks like some kind of locking behavior. However, what you are doing is inherently unpredictable, so the fact that it works consistently in one of those apps is nothing but pure chance (and woefully inefficient, at that, since you had to push the sleep times up to get the behavior you are seeing).
I agree that there must be something in one app that's not in the other. I've uploaded the forms/modules of the non-sleeping app and i can upload the forms/modules of the sleeping app and i would LOVE it if somone here could help me learn what's happening here. On both apps the multithreading is filling in columns of data at the same time. On one app the sleep is staggering the order in which that happens and in the other app it does not which is what this thread is about.
Quote:
Originally Posted by
Shaggy Hiker
1) You have an expectation for how threads work that is not based on a sound understanding of what they do. The book I would recommend would fix that, but it's neither small nor light in content.
2) You are using threads in a way that inherently relies on a race condition always coming out the same way. That's a dangerous design, because, even if you got it to work, it would only work most of the time, and the more different the conditions it ran in, the less likely it would be to work the way you expected.
1. what book
2. These threads are working on both apps regardless of what thread makes the workbook visible or which thread opens the workbook so they don't rely on a race condition coming out in the same way. Thead 1 can open the workbook or thread 6 can open the workbook. Either way the workbook is getting opened and the columns are getting filled by all the threads at the same time.
I'm trying to understand what is happening here.
If i'm only on the UI thread and i say
Thread1.start()
Sleep(10000)
'At this point in one application i'm 10 seconds into thread1 and in another application i'm not.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
If you really want to press this then I suggest you use a more ridiculous time in your original excel code. Use something like 10 seconds for your sleep, observe and tell us what happened. That may yield some clue.
I made some changes to this just to see how it would effect it.
Code:
Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
Dim testthread As New System.Threading.Thread(AddressOf Module1.testthis)
Dim testthread1 As New System.Threading.Thread(AddressOf Module1.testthis)
Dim testthread2 As New System.Threading.Thread(AddressOf Module1.testthis)
Dim testthread3 As New System.Threading.Thread(AddressOf Module1.testthis)
Dim testthread4 As New System.Threading.Thread(AddressOf Module1.testthis)
testthread.Start(1)
System.Threading.Thread.Sleep(20000)
testthread1.Start(2)
System.Threading.Thread.Sleep(20000)
testthread2.Start(3)
System.Threading.Thread.Sleep(20000)
testthread3.Start(4)
System.Threading.Thread.Sleep(20000)
testthread4.Start(5)
System.Threading.Thread.Sleep(20000)
Call Module1.testthis(6)
End Sub
Public Module Module1
Public loaded As Boolean
Dim xl = CreateObject("excel.application")
Public site1 As String
Dim xl1 As Microsoft.Office.Interop.Excel.Application = New Microsoft.Office.Interop.Excel.Application
Public Sub testthis(ByVal column As Integer)
Debug.Print("before visible " & column.ToString)
If xl1.Visible <> True Then
xl1.Visible = True
Debug.Print("after visible " & column.ToString)
End If
If xl1.ActiveWorkbook Is Nothing Then
xl1.Workbooks.Open("C:\Documents and Settings\BMcGuir1\Desktop\Test\spenddown in mdcd.xlsm")
Debug.Print("after open " & column.ToString)
End If
Dim y As Long
For y = 1 To 100
xl1.ActiveWorkbook.Sheets("sheet1").cells(y, column).value = y
System.Threading.Thread.Sleep(100)
Next
End Sub
End Module
Instead of creating an excel object I created a new exel.application
On the sleeping app only the first thread makes excel visible and only the first thread opens the workbook. When the second thread comes along it says exel is already visible so I won't debug.print anything and excel has already opened a workbook so i won't debug.print anything. I also added 20 second sleeps which caused cause some context switch messages but still all the threads were running at the same time regardless of sleep(20000) I just had to wait 120 seconds to see the excel spreadsheet being filled in.
How some after thread3 has made excel visible. So all the threads are hitting the
if excel visible <> true at the same time. Identifying that excel is not visible and stopping. If this is the case then why am I not getting an error when I try to make an already visible excel visible?
non sleeping app:
before visible 1
before visible 2
before visible 3
before visible 4
before visible 5
after visible 3
after visible 1
after visible 4
after visible 2
after visible 5
after open 6
after open 5
after open 1
after open 2
after open 3
after open 4
On the app where sleep() worksa and i'm sleeping for 2 seconds instead of 20 seconds:
Because the first thread has made exel visible and opened the workbook the other threads don't also make excel visible and open the workbook.
before visible 1
after visible 1
after open 1
before visible 2
before visible 3
before visible 4
before visible 5
before visible 6
-
Re: Sleep() not sleeping for some reason
Ok. Before the paintings of trolls start coming out in earnest, just one last try.
Program A and Program B do not work alike because there is no reason why they should. It really can't be difficult to grasp this. If Program A works the way you want it to then it is purely a matter of luck and in no way of judgement. It does not have to work that way, it may not always work that way, it just does at present. This is in no way due to your programming 'skills' and, by the same token, it is no way due to a lack of programming skills that Program B does not work the way you want it to. We cannot give you a solution to your 'problems' with Program B because there are none. It does not have to not work that way, it may not always not work that way, it just does at present. And there is nothing that you or anybody else can do about it.
If you want to program with multiple threads you must do so in a way that allows for the inherent unpredictability. That is all there is to it.
Now, you have your answer. Please mark this thread resolved and move on.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
dunfiddlin
Program A and Program B do not work alike because there is no reason why they should. It really can't be difficult to grasp this. If Program A works the way you want it to then it is purely a matter of luck and in no way of judgement.
Quote:
Originally Posted by
dunfiddlin
Now, you have your answer. Please mark this thread resolved and move on.
This actually made me laugh. I've come here to find out why the exact code behaves differently in program A than it does in program B and the answer i've been given is because program A is lucky? Why would I mark this thread resolved when your answer is that (when running the same code on the same computer with the same operating system under the same conditions) one program is lucky and one is not lucky.
I've read about programs that start a thread every time an employee makes or recieves a phone call and that thread records how long the phone call lasted. It does this with no unpredictiability. EVERY single call, thousands and thousands and thousands of calls per day have their length recorded as intended using threads of code that are operating under controlled and predicted conditions. The thread starts when the phone call starts, runs when the phone call is active, and the thread ends when the phone call ends.
Not only that but i've taken the code that i've discussed here and put it on 4 new applications and it behaved the same way in ever single application leading me to believe that there is some sort of predictability here.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
iamcpc
We are talking about two apps running on the same computer with the same OS, same everything.
That doesn't necessarily matter, as there are too many factors within the OS that are unknown. However, by this time, I would assume that you have run both several times each, and the pattern is consistent. That would mean that there really is some difference. Unfortunately, the difference need not be in your program, since you are working with Excel. Every application that is designed for multithreading has to deal with shared resources in some fashion. In your case, the Excel application itself is shared, and you are dealing with it by putting so much distance between threads that you are hoping they won't interact in a bad way. However, Excel could be sharing in some other way. The behavior you have shown, thus far, strongly suggests that there is a critical section somewhere along the path which is allowing only one thread at a time (and that includes the UI thread of the app itself, which is why all the other threads appear to happen later). Since you didn't create a critical section, then the likely culprit is internal to Excel. At that point, any explanation for why one app runs one way and another app runs a different way is pure speculation unless you find an expert on how Excel locks and releases objects. About the only thing you can do is examine the two programs side by side, and for any change in when or how you interact with the Excel object, or any objects within Excel, you could change one of the apps, then test again. Basically, it would be a whole lot of trial and error, because you probably can't tell in any other way what Excel is doing to cause the thread train.
As for the book, I didn't mention the title for a reason: I can't remember it. However, once I get home I'll track it down and post it. It's a very thorough book on the subject. Even if you don't read it all, you would probably find it interesting (maybe not pleasant, since it would strongly discourage the way you are going about this, but interesting nonetheless).
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
iamcpc
I've read about programs that start a thread every time an employee makes or recieves a phone call and that thread records how long the phone call lasted. It does this with no unpredictiability. EVERY single call, thousands and thousands and thousands of calls per day have their length recorded as intended using threads of code that are operating under controlled and predicted conditions. The thread starts when the phone call starts, runs when the phone call is active, and the thread ends when the phone call ends.
There are certainly a lot of programs written to use multithreading that work well. I've even written a few. However, the situation you describe with the phone calls seems fundamentally different from what you are trying to do. A single thread to deal with a single phone call, whoes lifespan is determined by the phone call, is a very reasonable way to go about things. Predicting the order of completion of those threads would require predicting the order of completion of the phone calls, which is clearly absurd in most cases. You are describing a situation where every thread is independent of any other thread, and can start and finish as needed. This is the way threads should be used. Many (if not nearly all) servers work by using a different thread for every connection request. The connection is handled in that one thread without regard for any other thread on the system, and it ends when it should. All the threads are independent. You can certainly make them dependent, though. All that is required is to have each thread run through some critical section. For instance, if every thread incremented a class level integer variable when it started, then decremented the integer when it finished, you would have to have those increments and decrements performed in critical sections, or the integer would soon be meaningless (in a multithreaded system, a statement like N += 1 could result in N, N+1, or N+X, where X is an arbitrarily large number). Once you have critical sections in multthreaded code, every thread will proceed through that critical section in the order that they arrive, and only when no other thread is in the critical section. At that point, your threads are interrelated, which is a much harder problem to solve.
In your case, your threads are interrelated intentionally. You want one thread to run at a time determined by threads around it (basically, one thread runs after another thread has finished). Furthermore, the behavior you are seeing certainly looks like the threads are stacking up at a critical section. However, you didn't create a critical section (you don't synchlock, monitor, grab a Mutex, or otherwise restrict) anything, so the critical section is probably in Excel itself. Figuring out where it is would be just trial and error...and kind of meaningless, since you'd be hard pressed to do anything useful with the information once you had it.
Quote:
Not only that but i've taken the code that i've discussed here and put it on 4 new applications and it behaved the same way in ever single application leading me to believe that there is some sort of predictability here.
That's a good step. So, now you have 5 that work in fashion A, and one that works in fashion B. The easiest thing to do would be to compare group A to group B, and see what is different about when things are done, and in what order, then try turning one of the group A into group B by changing just one thing at a time.
One thing that you have already determined is that all the threads are starting. That's what the breakpoints showed you. Further investigation along that line could show you at what line they stall while waiting for the UI thread to finish. That might help with figuring out what is different between A and B...but it might not, too. The threads are all running, they just get bottlenecked on some call in Excel, but only in some situations. The trick will be figuring out which situations cause the bottleneck, which might allow you to formulate a theory as to what Excel is locking on. The most likely situation is that Excel is locking some object (which you quite likely can't see, but it would look like it was locking a spreadsheet, workbook, app, or some other object you CAN see) and only one thread at a time can hold that lock. Therefore, the UI thread acquires the lock early on. Then, each subsequent thread proceeds until it gets to the point where it tries to acquire the lock, but since the UI thread already has it, the other thread goes to sleep. This happens for each thread until they are all sleeping at the point where they need a lock that the UI thread holds. Then the UI thread releases the lock, and the OS wakes up one thread (which one is not up to you, and isn't necessarily the first one in line), which acquires the lock (alternatively, they may ALL wake up, but only one gets the lock, so all the others go back to sleep), and proceeds. Once that thread releases the lock, the next thread acquires it, and so on.
The most reasonable place for the lock to occur is either on the workbook, or the cells. Moreover, the behavior you are seeing suggests that the lock is acquired before the line that writes, then released right after. Since the lock probably isn't really any of the objects you see (that could be dangerous), but is actually an object internal to Excel that you don't see (and may only exist for the purpose of locking), there really isn't anything you can say about it. The real question is why Excel is locking in one app and not in another, but I'd be a bit surprised if anybody around here would know what strategy the Excel team at MS used for synchronization of multiple users against a single spreadhseet.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
That's a good step. So, now you have 5 that work in fashion A, and one that works in fashion B. The easiest thing to do would be to compare group A to group B, and see what is different about when things are done, and in what order, then try turning one of the group A into group B by changing just one thing at a time.
I FIGURED IT OUT!!! OMG BEST ADVICE EVER.
OK the non sleep() sub there is a form1.webbrowser1 document completed event handler setting a global boolean variable in module 1 loaded to true if the document is completed and to false if the webbrowser is navigated or navigating. Why is this affecting how sleep() works? When I removed that changing of the value of the module 1 variable it works like my other 5 applications.
Why would this form1.webbrowser1 document completed event handler affect another thread?
Why would global variables affect how sleep works()
Is there a way that I can use this global variable and the webbrowser document completed event in a way that does not effect my threads and how sleep() works?
-
Re: Sleep() not sleeping for some reason
Sleep was never the issue. That was a red herring. You proved that with the breakpoints when you showed that the thread started. Sleep is working exactly how you would expect it to. The issue had to do with the lock that I was describing at the end of that second post. All the threads are getting bottled up trying to acquire a lock that is held by the UI thread, somewhere. Where the lock is I can't say, but the behavior fits. A global object (though not a boolean, I believe) would be a fine candidate for a lock, but since you didn't set one explicitly, it has to be something happening internal to one of the objects you were using. The WebBrowser may well be more likely than Excel to be the source of the lock, but there's a lock somewhere.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
Sleep was never the issue. That was a red herring. You proved that with the breakpoints when you showed that the thread started. Sleep is working exactly how you would expect it to. The issue had to do with the lock that I was describing at the end of that second post. All the threads are getting bottled up trying to acquire a lock that is held by the UI thread, somewhere. Where the lock is I can't say, but the behavior fits. A global object (though not a boolean, I believe) would be a fine candidate for a lock, but since you didn't set one explicitly, it has to be something happening internal to one of the objects you were using. The WebBrowser may well be more likely than Excel to be the source of the lock, but there's a lock somewhere.
The problem is with a global variable loaded and the form1.webbrowser1 document completed event setting that variable to true if the page is loaded and to false if the webbrowser is navigating read my previous post and let me know what you think about the questions that are boiling in my brain because of this.
-
Re: Sleep() not sleeping for some reason
Yeah, I read it. I don't believe the global variable could really be the issue, though. The WebBrowser might, since that's one that clearly seems like it would lock something.
One question though: What is the point of it all? After all, the result you appear to want would be done better without multithreading. Therefore, I have always assumed that you don't really care about the results you are talking about, and this is just an exercise to study multithreading. It's an interesting study, at that, but multithreading is a MASSIVELY difficult problem, as you are seeing. Behavior can be unpredictable even between two situations that appear identical. MS has been adding features to .NET to try to make multithreading more accessible, but they still have a ways to go. So, if you are doing this for the education, that's great, but if you really want the results for a specific reason other than just education, then threading isn't the way to do this. After all, you are making lots of use of sleep to cause different threads to operate in a sequential fashion, which means that you are paying the overhead of context switching to simulate single threaded behavior in a multithreaded implementation. Context switching isn't all that much, especially when threads are spending most of their time sleeping, but it certainly isn't efficient.
-
Re: Sleep() not sleeping for some reason
[QUOTE=Shaggy Hiker;4333711]Yeah, I read it. I don't believe the global variable could really be the issue, though. The WebBrowser might, since that's one that clearly seems like it would lock something.
QUOTE]
WORKS:
Code:
Private Sub WebBrowser1_Navigated(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserNavigatedEventArgs) Handles WebBrowser1.Navigated
'loaded = False
End Sub
Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
'loaded = True
End Sub
Does not work:
Code:
Private Sub WebBrowser1_Navigated(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserNavigatedEventArgs) Handles WebBrowser1.Navigated
loaded = False
End Sub
Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
loaded = True
End Sub
Even when I remove the webbrowser and change the variable on the form1 load event!
Works:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' loaded = True
End Sub
does not work:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
loaded = True
End Sub
Quote:
One question though: What is the point of it all? After all, the result you appear to want would be done better without multithreading.
The point was to better understand multithreading problems. To understand why threads were not running and completing when I testthread.start()
I even tested this with navingating the form1.webbrowser1 from another thread so that I could see
URL before navigate www.yahoo.com
start navigate to google thread on module1
sleep(100000)
url is still yahoo.
When I remove the global variables this is what happens
URL before navigate www.yahoo.com
start navigate to google thread on module1
sleep(100000)
url is now on google.
-
Re: Sleep() not sleeping for some reason
Doggone it. Now I'm curious. A Boolean can't lock, nor is that one doing so. So what IS it doing? Back in a bit.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
Doggone it. Now I'm curious. A Boolean can't lock, nor is that one doing so. So what IS it doing? Back in a bit.
Can the passing of variables between forms1 and modules lock?
LIke when I
Public loaded As Boolean in module 1 and then make loaded = false in form1?
-
Re: Sleep() not sleeping for some reason
No, it can't. Locks don't happen by accident. They are deliberate method calls that a programmer has to actively write, and they are never an accident. Since you didn't write a lock statement, who did? Only MS is a candidate, but there are almost certainly locks involved in webbrowsers, and probably in Excel.
So, for my first test, I took the code you posted and stripped out the Excel stuff. That stuff would be a bit painful to reproduce, though I may have to. That's kind of secondary, though. If Excel is locking some critical section when data is being entered, there would be nothing you could do about it, so it would be of only academic interest. In any case, in place of the xl object, I used a boolean and a string. The code worked as expected. When I shrank the sleeps in the main thread far enough, all four threads started at different times, and I logged them going through the loop sequentially. That was kind of interesting. Thread 1 would run one iteration, then thread 2 ran one iteration, then thread 3 ran one iteration, then thread 4, then 1, then 2, and so on. They all took turns because of the excesive use of sleep.
That then caused VS to crash. I'm not yet sure what the cause was.
-
Re: Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
No, it can't. Locks don't happen by accident. They are deliberate method calls that a programmer has to actively write, and they are never an accident. Since you didn't write a lock statement, who did? Only MS is a candidate, but there are almost certainly locks involved in webbrowsers, and probably in Excel.
So, for my first test, I took the code you posted and stripped out the Excel stuff. That stuff would be a bit painful to reproduce, though I may have to. That's kind of secondary, though. If Excel is locking some critical section when data is being entered, there would be nothing you could do about it, so it would be of only academic interest. In any case, in place of the xl object, I used a boolean and a string. The code worked as expected. When I shrank the sleeps in the main thread far enough, all four threads started at different times, and I logged them going through the loop sequentially. That was kind of interesting. Thread 1 would run one iteration, then thread 2 ran one iteration, then thread 3 ran one iteration, then thread 4, then 1, then 2, and so on. They all took turns because of the excesive use of sleep.
That then caused VS to crash. I'm not yet sure what the cause was.
Even with a lock each thread was stopping at each if statement when i had set my global variable
Each thread hit this and stopped untill every thread had hit this, so each thread is saying excel is not visible The same thing happened with opening the workbook. Each thread stopped at the if then for opening the workbook too.
-
Re: Sleep() not sleeping for some reason
So, after getting it all back, here's what I did next:
Removed any use of Excel, but wrote to a List (of String). This worked exactly as expected, regardless of what happened with the loaded variable. You might try the same thing to see if you get the same result.
Then, just for fun, I commented out all the Sleep statements. On the first attempt, all the threads ran almost sequentially, except that the UI thread ran between thread 2 and thread 3. That's because what I was doing was so fast that a thread would entirely complete before another thread could get set up. To get a more interesting result, I increased the number of iterations from 100 to 10,000. Around 1,800 on thread 1, thread 2 started. After that, the two threads were writing to the List in a total hodge-podge fashion.
I then tried moving the loop control variable y out to module scope so that it wasn't a thread-local variable. However, y doesn't get evaluated each iteration, so it didn't matter. Subsquent runs showed different and inconsistent behavior, as expected. Threads would run for a time, then stop for a time, then interleave for a time, and so on. Some didn't even appear to run concurrently, at times.
Of course, that's irrelevant. The key point is that I got the exact behavior I was expecting when I was writing to a List (of String) rather than to Excel. You could try that fairly easily, which would tell you whether or not it is Excel that is causing the behavior you are seeing. Of course, knowing that wouldn't help anything.
-
Re: Sleep() not sleeping for some reason
I'm marking this thread resolved because I stuck with it and figured out that a public variable was the ultimate find. I'm so glad it was not that one application was "lucky" and one was not! Thank you so much Shaggy for all your wisdom. Let me know about that multithreading book!
-
Re: [RESOLVED] Sleep() not sleeping for some reason
This is without a doubt the weirdest thing I've ever heard of.....A Boolean causing this kind of disturbance. Come to think of it though, when you rem out the code to set the Boolean variable, there remains no code in the event handler. It makes me wonder if the fact that there is code executing in the event handler is actually what accounts for your new discovery and not the Boolean itself.
-
Re: [RESOLVED] Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
This is without a doubt the weirdest thing I've ever heard of.....A Boolean causing this kind of disturbance. Come to think of it though, when you rem out the code to set the Boolean variable, there remains no code in the event handler. It makes me wonder if the fact that there is code executing in the event handler is actually what accounts for your new discovery and not the Boolean itself.
It's not the efent handler. It's the global variable
DOES NOT WORK:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox("hello")
loaded = true
End Sub
WORKS:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox("hello")
'loaded = true
End Sub
I tested it with a string variable too with the SAME results. Is there a better way to declare public or global application wide variables than making then public in a module? What is the difference between making them public in a module and sharing them?
DOES NOT WORK:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox("hello")
'loaded = true
site1 = "TRUE"
End Sub
WORKS:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MsgBox("hello")
'loaded = true
'site1 = "TRUE"
End Sub
-
Re: [RESOLVED] Sleep() not sleeping for some reason
I don't believe it was the Boolean. You can't lock on such a variable. What was happening went deeper than that, and probably involved Excel.
I took the code and stripped out the Excel from the module. In it's place I added a write to a List (of String). The resulting method was this:
Code:
Public Sub loop3(ByVal column As Object)
If xlBool <> True Then
xlBool = True
End If
Try
If Not xlString = "Spenddown IN Mdcd.xlsm" Then
'xl.workbooks.open("C:\Documents and Settings\BMcGuir1\Desktop\Test\spenddown in mdcd.xlsm")
myList.Add(column.ToString & ": Open")
For y As Integer = 1 To 10000
'xl.activeworkbook.sheets("sheet1").cells(y, column).value = y
myList.Add(column.ToString & ": " & y.ToString)
'System.Threading.Thread.Sleep(100)
Next
End If
Catch
'xl.workbooks.open("C:\Documents and Settings\BMcGuir1\Desktop\Test\spenddown in mdcd.xlsm")
End Try
'MsgBox("done")
End Sub
The program then ran as expected, with or without that Boolean even being in existence (I included it, as well as removing it completely). I also ran the code with and without all the Sleep calls. The results were always exactly as they should have been. With the sleep calls removed, the total unpredictability of threads showed up pretty well (though there had to be so many iterations that the output ended up HUGE). In some cases, each thread ran sequentially. The very next run would have the threads run out of order, or interleaved. That is as it should be. Adding the sleep statements caused such a huge delay between threads that they really couldn't ever run out of order, but getting them to interleave wasn't very hard (just remove the sleep statements between starting each thread, but leave the sleep statements between each loop, and they will interleave).
Since there are no critical sections, or synchronization controlling code, in the project, and since a Boolean can't be used as a lock, the problem pretty much has to be that Excel is locking differently based on how it is arrived at. I didn't test that explicitly. However, the only alternative is that the exact same code ran differently on my computer than on the OPs computer. That would be consistent with multithreading, in this situation, but would be slightly more disturbing.
The bottom line is this: Unsafe code is unsafe!
That design relies on a race condition always working out the same way, which is not guaranteed within a single program, let alone multiple programs. The fact that it ran correctly 100 times wouldn't change that in any way. Race conditions are totally nasty. It might run the way you expect for a couple years, then you might install some other program on the computer and this app may never work right again. That's what makes it unsafe: You can't predict the outcome of any one future run even when based on consistent performance over any length of previous runs.
In any case, the book is this:
Concurrent Programming on Windows by Joe Duffy. It covers how various newer Windows OS handle multithreading (there was a change with Vista from the model that had been in place since 2000, so the OS itself will impact how threads work), and deals with how the OS handles threading, along with how .NET handles threading. The book is not specific to .NET, but specific to Windows. Fortunately, it covers how .NET handles things and does so quite thoroughly.
-
Re: [RESOLVED] Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
I don't believe it was the Boolean. You can't lock on such a variable. What was happening went deeper than that, and probably involved Excel.
Since there are no critical sections, or synchronization controlling code, in the project, and since a Boolean can't be used as a lock, the problem pretty much has to be that Excel is locking differently based on how it is arrived at. I didn't test that explicitly. However, the only alternative is that the exact same code ran differently on my computer than on the OPs computer. That would be consistent with multithreading, in this situation, but would be slightly more disturbing.
In any case, the book is this:
Concurrent Programming on Windows by Joe Duffy. It covers how various newer Windows OS handle multithreading (there was a change with Vista from the model that had been in place since 2000, so the OS itself will impact how threads work), and deals with how the OS handles threading, along with how .NET handles threading. The book is not specific to .NET, but specific to Windows. Fortunately, it covers how .NET handles things and does so quite thoroughly.
I will read that book!
I tried it with a string variable in addition to a boolean and had the same problem. It looks like altering a public variable declared on a module from a form affects how that form creates threads which are an address of the module's subs or functions.
I tried it with having xl = createobject("excel.application")
on two seperate computers
(both the boolean and string global variables caused the problem)
I tried it with dm xl as microsoft.office.interop.excel.application = new microsoft.office.interop.excel.application
on two seperate computers
(both the boolean and string global variables caused the problem)
-
Re: [RESOLVED] Sleep() not sleeping for some reason
I don't believe that the global itself is the problem. I believe that it is Excel that is causing what you are seeing. You can test this for your self by using the variation that I posted which writes to a List (of String) and doesn't use Excel in any way. If you get the same behavior with Excel removed that you get with Excel present, then I am wrong and Excel is not to blame. However, if that is the case, then the behavior on my computer is different than the behavior on your computer, as the existence of the variable had no impact on the code on my computer.
-
Re: [RESOLVED] Sleep() not sleeping for some reason
This is indeed getting interesting. Try what Shaggy suggested and let us know the outcome. I'm really stumped on this one, like seriously.
-
Re: [RESOLVED] Sleep() not sleeping for some reason
Quote:
Originally Posted by
Shaggy Hiker
I don't believe that the global itself is the problem. I believe that it is Excel that is causing what you are seeing. You can test this for your self by using the variation that I posted which writes to a List (of String) and doesn't use Excel in any way. If you get the same behavior with Excel removed that you get with Excel present, then I am wrong and Excel is not to blame. However, if that is the case, then the behavior on my computer is different than the behavior on your computer, as the existence of the variable had no impact on the code on my computer.
I feel like it can't be just excel. If it was just excel the removing the changes to the global variable on form1 wouldn't change how the threads operate. It would have to be excel + global variable = problem. I'm going to try what you suggested just to see what happens
-
Re: [RESOLVED] Sleep() not sleeping for some reason
I agree with that. There is clearly some kind of interaction going on, so Excel + global variable may well be the problem. Alternatively, there is some chance that it is the WebBrowser, which is inherently thread related, but I didn't remove that, so Excel seems more likely to be the problem. The thing is that it can't be the global variable, alone, since there is nothing special about global variables and threading. One thing I didn't fully test is whether the default instances of the form had any impact. I didn't test this because I couldn't see how they would be, but since default instances have thread affinity while other instances do not, they could be having some impact.
Still, testing without Excel is the easiest test to perform, and if this does turn out to be Excel....it isn't even the weirdest thing I know of when it comes to Excel.
-
Re: [RESOLVED] Sleep() not sleeping for some reason
Quote:
Originally Posted by
Niya
This is indeed getting interesting. Try what Shaggy suggested and let us know the outcome. I'm really stumped on this one, like seriously.
Code:
Public Sub noexcel(ByVal column As Integer)
Debug.Print("before visible " & column.ToString)
If teststring = "0" Then
Debug.Print("thread changed site1:" & column)
teststring = column.ToString
End If
Dim y As Long
For y = 1 To 100
Debug.Print("threadloop loop: " & y & "thread number:" & column)
System.Threading.Thread.Sleep(100)
Next
End Sub
Global variable - excel = works as expected (thread 1 starts and ends 2 seconds before thread 2 because of the sleep between starting threads)
excel - global variable = works as expected (thread 1 starts and ends 2 seconds before thread 2 because of the sleep between starting threads)
excel + global variable = works but not as expected(including the UI thread) stop at making excel visible and opening the workbook. It appears that they are simultaneously making excel visible and simltaneously opening the workbook and simultaneously filling in the columns of data.
(all threads start looping and end looping at basically the same time)
-
Re: [RESOLVED] Sleep() not sleeping for some reason
So Excel is the culprit....I'm glad it turned out that way. I really don't know how I was gonna reconcile a simple Boolean causing such trouble.