Results 1 to 18 of 18

Thread: [RESOLVED] [2005] Setting text property across threads

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2005
    Location
    Lancashire UK
    Posts
    375

    Resolved [RESOLVED] [2005] Setting text property across threads

    I'm trying to set the text property of a ToolStripStatusLabel from within the DoWork method of a BackGround Worker.

    When I run the project I get a message telling me about an unsafe cross thread call, this I understand and expect

    The ToolStripStatusLabel does not support InvokeRequired so how do I check for cross thread calls and make a safe call to this control ?
    If my post helps , please feel free to rate it

  2. #2

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2005
    Location
    Lancashire UK
    Posts
    375

    Re: [2005] Setting text property across threads

    Ahh figured it out.
    If my post helps , please feel free to rate it

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

    Re: [RESOLVED] [2005] Setting text property across threads

    Firstly, for correctness, DoWork is an event, not a method.

    I think you may be mistaken about this error. I just tested it and it worked fine. That stands to reason because the ToolStripStatusLabel is not a control, nor does it host a control. Something like the ToolStripTextBox would be a different story, because it inherits ToolStripControlHost and does host a genuine control. In that case you'd do this:
    vb.net Code:
    1. If Me.ToolStripTextBox1.Control.InvokeRequired Then
    The ToolStripStatusLabel doesn't inherit ToolStripControlHost though, so it has no Control property. Can you do as I've done and add exception handling and attach a screen shot of the result?
    Attached Images Attached Images  
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2005
    Location
    Lancashire UK
    Posts
    375

    Re: [RESOLVED] [2005] Setting text property across threads

    I did the same as you and created a test project and it worked fine, however in my main project it still throws an exception if I try to access the ToolStripStatusLabel (which I've creatively called lbl2 )

    The two lines of code commented out above the Try - Catch block (which I've added just to generate the exception and get the exception message) are what Ive done to resolve this, and it works ok, but it's confusing that I'm getting this error when logically I shouldn't

    Name:  ex.jpg
Views: 562
Size:  43.2 KB


    Here's a more detailed exception message..

    Name:  ex2.jpg
Views: 545
Size:  117.3 KB
    Last edited by Tinbeard; Jul 13th, 2007 at 05:51 AM.
    If my post helps , please feel free to rate it

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

    Re: [RESOLVED] [2005] Setting text property across threads

    As your error message says, it's the StatusStrip that's causing the issue, not the ToolStripStatusLabel. I'm guessing that you have properties like auto-sizing the label to the text, so changing the text would cause the StatusStrip to execute code on the wrong thread. The StatsuStrip IS a control, unlike the ToolStripStatusLabel, so it DOES have an InvokeRequired property and an Invoke method, so your original issue doesn't exist. The control that's causing the issue is the StatusStrip so you use the members of the StatusStrip to marshal the cal to the UI thread.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

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

    Re: [RESOLVED] [2005] Setting text property across threads

    I just tried fiddling with a StatusStrip with two ToolStripStatusLabels in various configurations and I couldn't get it to throw that exception. I'd be interested to know what items you've added to your StatusStrip and what the property values are for the strip itself and each item.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2005
    Location
    Lancashire UK
    Posts
    375

    Re: [RESOLVED] [2005] Setting text property across threads

    I currently only have the one label on the StatusStrip and all the properties are default.

    Just in case something had become corrupt I deleted the label and added a new one but still got the same results

    So I deleted the StatusStrip and added a new one populated with the same label and.......... it works fine.

    The only thing I could think of is I had the original StatusStrip docked inside a ToolStripContainer, it's now docked within the form itself.

    So I added a new status strip with a label to the ToolStripContainer and when I accessed the text property from the doWork event the exception was thrown.
    If my post helps , please feel free to rate it

  8. #8
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    I couldn't help but notice that you said you had tried to access the ToolStripStatusLabel from within the DoWork event.
    That's not allowed since the DoWork event runs on a different thread than the UI thread.
    The BackGroundWorker ProgressChanged event runs in a handler that is in the UI thread and can be access from the form.
    Just remember to set the WorkerReportsProgress property to True or else you'll get an exception.

    So, if you actually did what you said you did and your code accesses anything from the DoWork event (whether or not it appears to be working) you should change the code so that it uses the ProgressChanged event instead.

    In fact, it might be good for you to re-run the test you set up and see if it works both ways. If it does, then you'll know that the problem was trying to access from the Worker thread in an improper way.

  9. #9
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    So you should call the BackGroundWorker ReportProgress method from within the DoWork event and everything should work fine.

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

    Re: [RESOLVED] [2005] Setting text property across threads

    Accessing a ToolStripStatusLabel from a worker thread IS allowed. The issue with multi-threading is that you cannot access members of a control from a thread that does not own its handle. The ToolStripStatusLabel is NOT a control, so there is no such restriction. If there was then it would have InvokeRequired and Invoke members.

    The problem here is that making a change to the label caused it to raise an event that was then handled by some other control. Thus some member of some control was accessed on a thread that didn't own its handle. From the details provided it appears that that control was the ToolStripContainer. The ToolStripContainer IS a control and therefore has Invoke and InvokeRequired members, thus allowing you to delegate.

    Using the BackgroundWorker's ProgressChanged event is a simple way to ensure that you don't run into this issue, but it's not suitable if you need to access different controls at different times. If you would need to do different things each time you call ReportProgress then I'd suggest using explicit delegation instead.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    Well I'm not familiar with the ToolStripStatusLabel; however, when I looked up ToolStripStatusLabel I found the following article in online help: ToolStripStatusLabel Control Overview.
    That did throw me off a bit, but I'll take your word for it, if it's not a control.
    However as you pointed out and as I suggesed, regardless of which was the offending control, using ReportProgress and Progress changed would simply eliminate any control on the UI thread from causing a problem since the call to update the label would then be coming from the UI thread.
    Therefore that was at least one safe solution.

    Just as a learning point for me... When you mentioned using explicit delegation were you refering to simply invoking a delegate and calling BeginInvoke on the Delegate and passing (possibly) a parameter, the CallBack function, and a state object; and then retrieving the IAsyncResult AsyncState to determine which was control would receive an update (as per appropriate state info being passed in)?

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

    Re: [RESOLVED] [2005] Setting text property across threads

    The problem with using the ReportProgress method and ProgressChanged event of a BackgroundWorker is that you can only pass two parameters to ReportProgress: a number representing the percentage progress and an Object. That Object can be whatever you want but it can only be one object and it is accessed in the ProgressChanged event handler via an Object reference.

    That's fine if you only ever want to do one thing. You know exactly what that object is so you can cast and use it. If you might want to access multiple controls at different times then things soon become very messy. You'd have to test the type of the object before casting, plus you'd have to have a different type of object for each task you wanted to perform. Let's say that you might want to add an item to a ListView or display an image in a PictureBox. How would you do both at different times via the ReportProgress method? It would be possible but messy.

    It would be preferable to write your own methods and delegates to perfrom those tasks and invoke them directly rather than relying on the BackgroundWorker to marshal the calls to the UI thread.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  13. #13
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    Ok, so the method I refered to in my post #11 -- is that the way you'd handle this? Or are you thinking of something different?

    Thanks

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

    Re: [RESOLVED] [2005] Setting text property across threads

    As I said, if the situation is simple, i.e. you only want to perform one cross-thread task, then using the BackgroundWorker's ReportProgress method is generally a good option. If there are multiple tasks to be perfromed at different times then it is not because the code would get messy.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  15. #15
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    I'm sorry I meant the last part of my post:

    Just as a learning point for me... When you mentioned using explicit delegation were you refering to simply invoking a delegate and calling BeginInvoke on the Delegate and passing (possibly) a parameter, the CallBack function, and a state object; and then retrieving the IAsyncResult AsyncState to determine which was control would receive an update (as per appropriate state info being passed in)?

    Are you talking about using a class to maintain info on the calling object?
    What I mean is this, create an object to hold info on which control should be accessed on the UI and then let that object ride round trip throught the Delegate and the CallBack?

    Or just making different delegates for each situation?

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

    Re: [RESOLVED] [2005] Setting text property across threads

    Quote Originally Posted by FourBlades
    I'm sorry I meant the last part of my post:

    Just as a learning point for me... When you mentioned using explicit delegation were you refering to simply invoking a delegate and calling BeginInvoke on the Delegate and passing (possibly) a parameter, the CallBack function, and a state object; and then retrieving the IAsyncResult AsyncState to determine which was control would receive an update (as per appropriate state info being passed in)?

    Are you talking about using a class to maintain info on the calling object?
    What I mean is this, create an object to hold info on which control should be accessed on the UI and then let that object ride round trip throught the Delegate and the CallBack?

    Or just making different delegates for each situation?
    If you only have one task to perform, like set the Text of the same Label over and over, then I'd use the ReportProgress method of a BackgroundWorker. If you have to perform the same task but on different controls at different times, then I'd create a single method and a single delegate to handle them all. If you have different tasks to perform on different controls at different times then I'd create a distinct method and delegate for each. There's no need for any IAsynchResults at all.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  17. #17
    Frenzied Member
    Join Date
    Aug 2006
    Posts
    1,051

    Re: [RESOLVED] [2005] Setting text property across threads

    Ok, got it!
    I just couldn't wrap my mind around the differences. Although, it should have been easy.
    Thanks again, jm

  18. #18

    Thread Starter
    Hyperactive Member
    Join Date
    Aug 2005
    Location
    Lancashire UK
    Posts
    375

    Re: [RESOLVED] [2005] Setting text property across threads

    Thanks for taking the time to look at this for me and explain what's going on, learned something new again

    My first time with multi threading so still on the learning curve.
    If my post helps , please feel free to rate it

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