Get Rid of "(Not Responding") tag in title bar.

BluAvi

Member
Joined
Jul 31, 2007
Messages
6
Programming Experience
1-3
Hi all, this is my first post here. Rather than tell you my life story, I'll just ask a question.

I'm working on a rather large (60+ forms, OK maybe not that large, but its the biggest one I've done). Anyway, some of the processes that take place apparently eat up a bunch of memory. When it does this, it will sometimes display "Not responding" in the title bar, as well as the task bar. Is there any way to get rid of this? Perhaps a check when it's done processing?

~Avi
 
I'm guessing the reason you are seeing Not Responding in your forms title is because you have some activity in the forms thread. Due to this the form cannot process events in the GUI. I suppose repainting would be one of those events.

My suggestion would be to do the major work in a separate thread. Multithreading is fairly easy to do in VB.NET, but there are some things that can get you. Such as cross-threading and race conditions.

You should be able to find a few examples of multithreading, but if you give me some more background as to what you are looking to do I may be able to provide a more tailored example to show you.
 
Hi all, this is my first post here. Rather than tell you my life story, I'll just ask a question.

I'm working on a rather large (60+ forms, OK maybe not that large, but its the biggest one I've done). Anyway, some of the processes that take place apparently eat up a bunch of memory. When it does this, it will sometimes display "Not responding" in the title bar, as well as the task bar. Is there any way to get rid of this? Perhaps a check when it's done processing?

~Avi

Hauptra is right; here's a brief rundown of how windows works. Every window has a message queue and messages are posted into that queue by a variety of thigns like keypresses, user mouse movements and clicks etc. By default, a procedure consumes the messages, passing them out to the relevant controls within the window. The thread that does the consuming is the same one that created the window, and when you write code, that thread also runs your code. If your code is so complex that it takes a long time to run then that thread is busy with your code and cannot consume the windowing messages. Windows XP itself notices that the queue is growing unattended and puts the [Not Responding] in the titlebar.

To solve the problem, dont do long running ops on the main window thread, use a BackgroundWorker instead. If a progress display is required, again use the BackgroundWorker. DONT try to update a control from within the background worker's DoWork() method, because the code in there is being run by a different thread. Windows must ONLY be updated by the thread that created them, and background worker caters for this with the DoWork(). Without it, you have to get into the ugly coding of delegate invokes (which can be a little hard to understand at first)

Another thing worth noting:
DONT create any new windows within your DoWork() sub either - those windows will be created by the background thread, and as soon as the thread is finished and dies, it stops processing window messages, meaning your new window will just hang. You should always use the ReportProgress() function (and ensure the relevant ProgressChanged() event is handled) of background worker to update or create ANYTHIUNG to do with the GUI!
 
Visual Studio 2005 is pretty good about not letting you modify a form from within a different thread. The Visual Studio help also has a decent example to show you how to get around this if you need to.

All you really need to do is create a delegate for a property and within the property check if InvokeRequired is true. if so then invoke the delegate using the property that you created. If InvokeRequired is false then you simply do the work.
 
All you really need to do is create a delegate for a property and within the property check if InvokeRequired is true. if so then invoke the delegate using the property that you created. If InvokeRequired is false then you simply do the work.

You may think of it as simple, because you know; as Chris Tarrant (WWTBA Millionaire host) says "It's only simple if you know the answer"

What you wrote there, to someone who has no idea about threading, invokation or delegates, will be complete gobbledegook I'm afriad. Heck, I know that stuff and I'm not even sure I understand it.

BackgroundWOrker makes the process as painless as possible:

Add a BGW to your form
Handle the BGW.DoWork event to do your work
For progress reports, set BGW.ReportsProgress = True, and handle the ProgressChanged event

Obey the rules: Never access a gui control within DoWork (dowork should be given all the info it needs to do its work), never create a form in DoWork, and always call BGW.ReportProgress() to pass info to the ProgressChanged event that updates controls.
 
Wow, thanks.

I'll give this stuff a try and let you know how it turns out. (researching multithreading) sounds interesting.

~Avi
 
I agree with you in that you shouldn't interact with your GUI through your worker thread. However using Delegates in conjunction with the InvokeRequired and Invoke methods it is possible to interact. The interactions are occurring in the GUI thread though. As for me saying that it is simple, I mean by way of # of lines of code.

For Example

VB.NET:
Private Delegate Sub SetTextDelegate(ByVal value As Integer)

    Private Sub SetText(ByVal value As Integer)
        If Me.InvokeRequired Then
            Me.Invoke(New SetTextDelegate(AddressOf SetText), value)
        Else
            Me.Text = value.ToString
        End If
    End Sub
 
BackgroundWorker is a component you can find in the toolbox, making most of the "code lines" generated with a few mouse clicks.

The underlying AsyncOperation class that the BackgroundWorker is using to keep the calls to UI elements in safe context is also easy to work with.
 
I agree with you in that you shouldn't interact with your GUI through your worker thread. However using Delegates in conjunction with the InvokeRequired and Invoke methods it is possible to interact. The interactions are occurring in the GUI thread though.

Yep, though what I'm saying about BGW is that it does the delegation for you and hides the complexity:

VB.NET:
  Public Sub DoWork()
    bgw.ReportProgress(0, "Starting Long Op 1")
    DoLongOperation1()
    bgw.ReportProgress(0, "Starting Long Op 2")
    DoLongOperation1()
    bgw.ReportProgress(0, "Done")
  End Sub

  Public Sub bgw_ProgressChanged(percent as Int32, userState as Object) Handles bgw.ProgressChanged
    myLabel.Text = e.UserState.Tostring()
  End Sub

As for me saying that it is simple, I mean by way of # of lines of code.
I reckon my 1 line is simpler than your 5 :D
 
Well, so far it looks like my app is too large to make implementing multithreading worthwhile... its not that multithreading is difficult I just didn't know about it (newb)... and now the whole thing is kinda big... so.. any other ideas?

~Avi
 
Addressing the problem related to this post specifically, the reason why you are getting "Not Responding" in the title bar is because of the work being done in the main thread.

I'm open to anyone else's suggestions, but my opinion is that the best answer to this problem is using multithreading. Any other solution to this problem is a hack IMO.

Maybe you could provide a piece of code that is particularly difficult to convert to multi threaded and a solution could be suggested.

Rob
 
Well, so far it looks like my app is too large to make implementing multithreading worthwhile... its not that multithreading is difficult I just didn't know about it (newb)... and now the whole thing is kinda big... so.. any other ideas?

~Avi

Too large? What does that mean anyway?

What's hard about this:

Drop a BackgroundWorker on the form that does the work
Go to the BGW events properties and double click the DoWork() item
Type one line of code that points to the sub you call to do the work
Change the button handler that kicks off the work, to one line of code saying:
If Not bgw.IsBusy Then bgw.RunWorkerAsync()
 
I appologize, I'm still fairly new to programming... but I dont think it's that simple... I keep getting cross thread errors when I try to do what you are suggesting.

The application is a purchase order system that is designed to aquire connections to both a universe system, as well as an sql server. these have to remain open while the process is occuring. The Process also updates, as well as gets inputs, from a datagrid. The cross threading is occuring with the datagrid.

The reason I said that it probably wasn't fesable was that there are alot of controls involved that would cause cross threading violations... unless of course you could suggest a way around them.

~Avi
 
Back
Top