Results 1 to 20 of 20

Thread: [2005] threading problem

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    [2005] threading problem

    Oh boy a threading problem! I bet you guys never get any of those lol. I've got a sub that does some database stuff but mainly you need to know this part of it:

    Code:
                m_Connection.Open()
                count = cmd.ExecuteNonQuery()
                m_Connection.Close()
    So what's apparently happening according to the error is back in the main code I call the thread attached to this sub and it gets all the way through my loop and back to telling the thread again. Then it crashes saying that the connection's state is already open so it can't be opened. So I thought it's running a second version of the sub/thread but when I walk through it in debug, it gets to the nonQueryThread.Start() command for the second time and says it can't start the thread because it's already running. So I'm not really sure why it didn't crash on that before. Does it just not start the thread and keep going without crashing and whatever happens, oh well?

    Anyway, later in my program I need to do the same thing but pretty much the next line after the start thread command it needs to do something with the resulting datatable of that thread to be there so how can I get my program to wait for that thread to get done before doing anything else?
    And if you recall, I'm putting all the database stuff in seperate subs/threads because it's screwing with my progress label refreshing on the form and causing it to not refresh if I do pretty much anything. If I tell my program to wait for that thread to finish would that cause the same problem?


    Oh and if anyone knows how I can do this other idea, then forget all that crap above. If I just put the form refresh sub in a seperate thread I think that would in theory, keep the form from freezing up. But of course I can't access the form from inside another thread because of the big sharing permissions problem thing that I have no idea how to get around. So if anyone knows how to just make sure the form's refresh sub actually refreshes it, that'd help too
    Last edited by Desolator144; Jan 8th, 2008 at 01:16 PM.
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2005] threading problem

    Yeah, if you pause the UI thread waiting for another thread to finish, then the UI will pause, which means no screen updates. A better solution would be to have the thread raise an event in the UI thread when the datatable is ready. The UI thread would then handle the event to know when it was safe to continue. If invoking a control is an option, you could go that route. Otherwise, raising an event on a different thread is easy to do, but strangely hard to find documentation for it. If that sounds like what you want to do, you could search this forum for SynchronizationContext. I posted a solution to this problem, and I believe I explained the necessary steps, which are few. Frankly, the solution, while easy, feels hokey to me, but I have tested it extensively, and it works nicely.

    As for the first thing, it sounds like the connection isn't closing. There are a couple options you might consider, including leaving the connection open, since you apparently use it repeatedly in short order, as well as checking the state of the connection and using it if it is still open. Why it would be still open I can't say, but you did allude to the fact that the code you posted is trimmed for presentation.
    My usual boring signature: Nothing

  3. #3
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    It looks like the calls on the different threads are trying to access the same connection. If that's the case, I assume you're using some type of static/singleton (whatever the hell it's called) object for your db access.

    Just give it the ThreadStatic Attribute and the app will create one instance for each thread rather than just use the same instance for all the threads and this will avoid that problem.

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    Re: [2005] threading problem

    Well I'm thinking just leaving the connection open sounds like the best idea lol. Can't believe I didn't think of that. In fact you hit Start and my program database IO for like 3 minutes and then it's done and that's it. So i should probably just open the connection at the beginning and close it at the end of the program :P
    EDIT: lol I took out the open and close connection command in every loop and now it's over 5x faster

    But of course I just realized an even worse problem. No matter how I fix it, in one loop every update command needs to finish completely before the next one or the whole thing will explode cuz the database won't accept it. So I still can't let the program continue until that thread is done. Actually if I fix it so the entire thing event based, that would fix it 100% and it would be perfect and also run as fast as possible. But of course I'd have to re-write my entire program from linear with loops to threads calling each other through events. And it's a massive program so I don't have time before the deadline

    You know, all I want to do is get the stupid label to refresh. And it's way too much of a hasle to move the other 95% of my code into another thread just to let one stupid label say something. That's why I came up with another tricky idea I wanted to run past you guys. Could I make a new sub and give it its own thread and inside the sub instantiate a small, borderless form on top of my existing form where the label control would be and have a label control inside that new form display the progress data (like "Importing record 5 of 109")? If that would even work, I could just make the string that it should display a module level variable and the thread should be able to access it, right? I might just try that. Btw I'm doing it all with a 2nd form because if I try to access a control on the existing form from another thread...
    "Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on."
    yeah blah blah blah, access it anyway, it's in the same assembly you stupid debugger.
    Last edited by Desolator144; Jan 8th, 2008 at 03:22 PM.
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2005] threading problem

    Does the 5x increase change the basic question? If you were to refresh the form after every update, the label would get updated that often, which with the faster execution might be fast enough?
    My usual boring signature: Nothing

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    Re: [2005] threading problem

    funny you should mention that cuz now that it doesn't have to waste like 80% of the processing cycles on opening and closing the connection, I can't get the label to freeze up but of course that's on my supercomputer. I bet if I tried it on a slower one, it'd still have the same problem.
    Btw I extensively tested the form on top another form theory and it turns out if you declare the form module level and then as new and .show it the first time through the new sub/thread is called and then every other time just update the label control the new form contains, it crashes because apparently every time the thread/sub is called, it's a new thread and can't access the form it made the first time I could declare and open and place a new form every time with an updated label but I don't think anyone's computer is fast enough to render that. Apparently mine's not.

    Isn't there just a way to give my stupid original label control permissions so that every thread can access it? I tried changing its modifiers to public which I thought means threads that aren't even in the same assembly can alter its properties but I guess not cuz it didn't work
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  7. #7
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    Quote Originally Posted by Desolator144

    Isn't there just a way to give my stupid original label control permissions so that every thread can access it? I tried changing its modifiers to public which I thought means threads that aren't even in the same assembly can alter its properties but I guess not cuz it didn't work
    Do you mean the "Cross-thread operation not valid: Control '<name>' accessed from a thread other than the thread it was created on" exception that you get when you try and change the value of a control on your form from a worker thread?

    I just put a try-catch block around where I update that control and ignore the exception. It seems like it could have some use for large, multi-threaded applications, but when you just want to update a label or something, it's kind of overkill to worry about it. There is some way to code the update to the label in a thread-safe manner, but it just seems to be overly complex for something as basic as this when you know that there's no issue in updating the label.

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    Re: [2005] threading problem

    wait, you're telling me it raises the error in VS but still actually runs the command anyway in the real world? I thought if I let it out that way as soon as it tried to access the control, the computer would blue screen.
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  9. #9
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2005] threading problem

    I believe to change a control, which is in the UI thread, from any other thread, you use Invoke. I think Atheist posted an example in the last few days. I have always been raising events from background threads, and none of them have ever had to alter a control directly, so I've never tried it.

    Theoretically, you can have a single object and let all threads access it willy-nilly. It's almost certainly a bad idea, and in many instances will lead to crashes that are too inconsistent to be positively classified, which makes them a nightmare to debug. However, since you can alter a different object by multiple threads, why not a control? Somebody might know the answer to this, but it sounds like Tom Sawyer is saying that he does just that. Perhaps the label text can be changed, but that change triggers an event (Paint) which, coming from the wrong thread, causes the exception. The change still takes place, because the exception comes from something else.
    My usual boring signature: Nothing

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    Re: [2005] threading problem

    well this kinda sucks now cuz I can't tell when a slower computer would render it or not without actually putting the program on a slower computer. But I've been thinking and me.refresh() basically tells the form that its graphical status is invalid and it should redraw everything whenever it feels like it. But if I put me.refresh() followed by me.update() that would work, right? Update says it "causes the control to redraw its invalidated client area" So I think that'd be like the "yeah and do it now" that it needs to actually refresh it. I remember using update for something once, probably my timer program, and it actually worked. What do you guys think? Is that a decent fix?

    actually shouldn't I be doing:
    lblStatus.Refresh()
    lblStatus.Update()

    hey I tried replacing all the commands with that and it really, really worked cuz the rest of the form was frozen and had chunks missing out of it when I came back but the label kept updating. Hurray! Now time to change it back to form-wide lol
    Last edited by Desolator144; Jan 8th, 2008 at 06:21 PM.
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2005] threading problem

    I think Me.Refresh invalidates the entire client area, so that Me.Update is unnecessary. I've used Me.Refresh in several programs to deal with situations similar to what I think you are describing, and it has always been sufficient.

    How much difference do you think there is between the two computers? Is the primary computer REALLY fast, as in multiple times as fast as the slower one? If not, I wouldn't expect much difference. This isn't an FPS, where frame rates of 30 fps or better are needed. The screen is re-drawing only a small area, and it will be a very minor drawing operation compared to any 3D game....unless this is a 3D game. You would have to test, but if it works well on a great computer, I would expect it to work fine on a pretty fair computer, as well.
    My usual boring signature: Nothing

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2005
    Posts
    257

    Re: [2005] threading problem

    nopers, just a database program. Takes XML from a website of ppl who signed up and sticks em in an Access DB. But the speed it's going now it loops about 50 times per second so that's almost the screen's refresh rate in label refreshes. So hopefully another computer can render that. Mine's a 4400+ X2 and this could be run on just about anything. Mostly old, slow laptops in the field.
    Now I figure that the label's text change event invalidates the graphics so if I don't do a me.refresh to invalidate everything, I can just do a me.update and it will only redraw the label and anything else that's been invalidated which should be more efficient. I'll have to try that later
    I tried to end process on Visual Studio 2005
    but PETA stopped me saying it's smart enough
    to be a living creature

  13. #13
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    Quote Originally Posted by Desolator144
    wait, you're telling me it raises the error in VS but still actually runs the command anyway in the real world? I thought if I let it out that way as soon as it tried to access the control, the computer would blue screen.
    No, it crashes the program both in VS and in the real world. What I'm saying is that it's an irrelevant error. There are, of course, situations where you don't want background threads to be able to have access to your UI but when you just want a worker thread to notify the user that it's done, then this error check is overkill.

    What I do is change:

    Code:
    lblNotify.Text = "Done"
    Which raises a threading error because a worker thread is trying to update the form to:

    Code:
    try
        lblNotify.Text = "Done"
    catch ex as Exception
    end try
    There is a way to use an Invoke command to give your thread access to be able to change the text and using try/catch blocks as part of normal processing is, of course, a hack, but it's too much trouble to make the code thread safe for something this basic and mundane.

  14. #14
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: [2005] threading problem

    Quote Originally Posted by Tom Sawyer
    No, it crashes the program both in VS and in the real world. What I'm saying is that it's an irrelevant error. There are, of course, situations where you don't want background threads to be able to have access to your UI but when you just want a worker thread to notify the user that it's done, then this error check is overkill.

    What I do is change:

    Code:
    lblNotify.Text = "Done"
    Which raises a threading error because a worker thread is trying to update the form to:

    Code:
    try
        lblNotify.Text = "Done"
    catch ex as Exception
    end try
    There is a way to use an Invoke command to give your thread access to be able to change the text and using try/catch blocks as part of normal processing is, of course, a hack, but it's too much trouble to make the code thread safe for something this basic and mundane.
    Its unnecessary to have exceptions thrown when you can avoid it, as they are resource-hogs.

    Heres an example of how to access controls from worker threads:
    VB.Net Code:
    1. Private Sub MethodRunningOnAWorkerThread()
    2.         ChangeLabel1Text("Hello world")
    3.     End Sub
    4.  
    5.     Private Delegate Sub StringDelegate(ByVal str As String)
    6.     Private Sub ChangeLabel1Text(ByVal str As String)
    7.         If Label1.InvokeRequired Then
    8.             Label1.Invoke(New StringDelegate(AddressOf ChangeLabel1Text), str)
    9.         Else
    10.             Label1.Text = str
    11.         End If
    12.     End Sub
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  15. #15
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    A worse resource hog than creating and invoking delegates? I gotta figure that that's a wash.

    While it's certainly better coding practice to do it that way and ignoring exceptions is bad coding practice in most cases, updating a label from a worker thread to say that it's done something is such a simplistic action that I find it somewhat offensive that they're gone and made it an error. This is especially true when the code worked fine in VB 2003 but then started throwing errors in 2005 when I upgraded it. It annoyed me so much that I made a moral decision to refuse to deal with it. It's just unecessarily complex for such a basic operation and I don't like having to create delegates for such simplistic tasks.

  16. #16
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: [2005] threading problem

    Quote Originally Posted by Tom Sawyer
    A worse resource hog than creating and invoking delegates? I gotta figure that that's a wash.

    While it's certainly better coding practice to do it that way and ignoring exceptions is bad coding practice in most cases, updating a label from a worker thread to say that it's done something is such a simplistic action that I find it somewhat offensive that they're gone and made it an error. This is especially true when the code worked fine in VB 2003 but then started throwing errors in 2005 when I upgraded it. It annoyed me so much that I made a moral decision to refuse to deal with it. It's just unecessarily complex for such a basic operation and I don't like having to create delegates for such simplistic tasks.
    If you're agreeing on the fact that catching and ignoring exceptions is a bad practise, then why are you recommending it? I just tried your approach to the problem, but it didnt update my label. Since an exception is thrown, the line isnt executed properly.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  17. #17
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,109

    Re: [2005] threading problem

    I find the invoke process unnecessarily cumbersome, as well, but it may be a necessary evil. So far, I have always avoided it because background threads talked to the UI thread, not to the user, so no user interface changes were needed. I was just raising events from the background thread, which is easier, though not well documented.

    Of course, the end result is pretty much the same, since if you have the background thread raise an event on the UI thread, then the UI thread would have to handle the event for it to be meaningful, and handling the event is about the same as the Invoke in the first place.
    My usual boring signature: Nothing

  18. #18
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: [2005] threading problem

    Quote Originally Posted by Shaggy Hiker
    I find the invoke process unnecessarily cumbersome, as well, but it may be a necessary evil. So far, I have always avoided it because background threads talked to the UI thread, not to the user, so no user interface changes were needed. I was just raising events from the background thread, which is easier, though not well documented.

    Of course, the end result is pretty much the same, since if you have the background thread raise an event on the UI thread, then the UI thread would have to handle the event for it to be meaningful, and handling the event is about the same as the Invoke in the first place.
    Yeah I agree that it sometimes can be cumbersome, but you can always create a method that takes a control argument, so you can change the text property for any control..that way you dont need to create one for each control:

    VB.Net Code:
    1. Private Sub MethodRunningOnAWorkerThread()
    2.         ChangeControlText(Label1, "Hello world")
    3.     End Sub
    4.  
    5.     Private Delegate Sub ControlStringDelegate(ByVal ctrl As Control, ByVal str As String)
    6.     Private Sub ChangeControlText(ByVal ctrl As Control, ByVal str As String)
    7.         If ctrl.InvokeRequired Then
    8.             ctrl.Invoke(New ControlStringDelegate(AddressOf ChangeControlText), ctrl, str)
    9.         Else
    10.             ctrl.Text = str
    11.         End If
    12.     End Sub

    Just make sure the control you're passing into it has a text property.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  19. #19
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    Quote Originally Posted by Atheist
    If you're agreeing on the fact that catching and ignoring exceptions is a bad practise, then why are you recommending it? I just tried your approach to the problem, but it didnt update my label. Since an exception is thrown, the line isnt executed properly.
    Hey, you're right. It hoses on the .Text fields.

    This is weird because it works fine for updating datepickers and enabling buttons (which is how I use it), so I assumed that updating a label would be the same.

    It looks like not only was this a poorly thought out, badly implemented and completely unecessary addition to the 2005 framework, but they didn't bother to test it either.

  20. #20
    Frenzied Member
    Join Date
    May 2006
    Location
    Toronto, ON
    Posts
    1,093

    Re: [2005] threading problem

    Grr...

    It looks like the Form.Activate() acts like the .Text field and throws the error before changing the value instead of like the .Enabled fields which throw the error after changing the value, so I had to go and use the invoke command anyways in order to have my form pop up when the thread was done.

    I was hoping to be able to avoid using it in protest of this stupid change.

Posting Permissions

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



Click Here to Expand Forum to Full Width