I am using a Google map inside of vb.net application. The problem is that it keeps taking a memory space whenever I search a map on a web browser which is on a windows form . Even though I close the form, it is not disappeared from memory. The size of memory is just going up. That goes away when I close MDI form.
What is the solution for this? How do I manage the memory problem?
-->Edited : One of out team member found the solution. It worked out pretty well. Just call the function whenever you want to do it. I used it on Form Closing event.
<DllImport("psapi.dll")> _
Public Function EmptyWorkingSet(ByVal hProcess As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Function GetCurrentProcess() As IntPtr
End Function
Public Sub FreeMemory()
EmptyWorkingSet(GetCurrentProcess())
End Sub
Check out my answer to this question. I believe your best bet is to do some profiling.
I ran the trial version of ANTS memory profiler, against an app I was working on and the problem I discovered is outlined in this walthrough of how to use the tool (specifically the details around figures 10 - 15).
Basically, I was subscribing to some events on a form, but then not unsubscribing from them when the form was closed. This meant there was still a reference to the form and it (along with all it's controls and members) were never collected.
Maybe you have a similar situation, but your best bet is to look at the code in a profiler. It doesn't have to be this one (this is just the one I've used). It will certainly help you identify the root cause of your problem.
This is from the liberal garbage collection in .NET. If you're really concerned about memory, try this.
First, ensure that the objects you wish to remove have been disposed. If this is a Windows Form, this should be automatic.
Call System.GC.Collect(). You should see your memory usage decrease.
As a work around you could use an MDI parent and put your maps into MDI child forms opening up a new one each time (or periodically closing unused ones)?
Related
I'm trying to implement an API Hooking mechanism.
What I have so far, is a DLL injected into other processes via a SetWindowsHookEx call, and some code to implement the hooks themselves.
For example, I can successfully hook MessageBoxA calls across multiple different applications (thats not the end goal).
What I need to do is hook some graphics functions, in particular textout functions as I need to be able to screen scrape.
Now - I'm aware which textout functions I need (TextOutA/W, ExtTextOutA/W for the application I'm trying to access), and I'm aware I need to hook Begin/EndPaint or Get/ReleaseDC to match the DC's to window handles and determine if the textout is on a window I'm interested in.
My problem is that while I can hook the textout functions, messageboxes and so on without any problems what so ever, GetDC results in a hard crash as does BeginPaint.
The code is quite long, so I'll post what I'm having problems with, but I can post more if it helps.
The rough frame work is as follows;
function CustomBeginPaint(hWnd: HWND; var lpPaint: TPaintStruct): HDC;
begin
UninstallHook();
Result := BeginPaint(hWnd, lpPaint );
InstallHook();
end;
Even this quite simple function fails constantly, returning zero.
I'm at a complete loss to explain whats going on, as the hWnd is always 1309192 despite trying this on multiple machines.
So the key issue was, as Andreas Hausladen mentioned thread safety - but not due to the VCL.
I'm developing a DirectShow CSource capture filter. It works fine, but when I close the program that is using the filter (in this case I'm testing with VLC, but the same happens with other programs), the program crashes (if I'm debugging it in Visual Studio then a breakpoint is triggered).
I've been hunting down this problem for some time now and found that both, my source filter and my source stream are not being released; this is, their reference counter is 1 at the end of the program, DllCanUnloadNow() function reports that there are 2 objects still in use, and, when CoUninitialize() is invoked, the program crashes.
I'm pretty sure that the reference counters are being handled correctly since I'm using the base classes implementation. The only unusual thing in my software that I can think of is that I'm using my own version of DllGetClassObject(): I configured the .DEF file to have MyDllGetClassObject() exported instead of DllGetClassObject() so I could insert some code before invoking the default implementation. I don't think this is a problem since I've checked that the reference counter of all objects I return at the end of MyDllGetClassObject() is 1.
I guess I'm missing something about the lifecycle of the filter, but can't figure out what (this is the very first capture filter I'm developing). Any suggestion?
Thank you in advance,
Guillermo
I finally figured out what was going on. The static method InitializeInstance in my source filter is invoked with bLoading == false and rclsid == <the GUID of my filter> at process shutdown. That seems to be the appropriate place to release that remaining reference counter from the filter instance.
I got the key idea of how important is to release all COM objects before CoUninitialize some time ago from another post on StackOverflow entitled DirectShow code crashes after exit (PushSourceDesktop sample). All I needed was just a little bit more knowledge on DirectShow filters lifecycle.
Anyway, thank you for your efforts, Roman, I know how vague this thread sounded from the beginning :)
I have a program written in VB 2010 express under windows xp which does some heavy number crunching combined with serial communication. When it "gets too busy" it does not update the screen anymore (done simply with Textbox.text = "any text") and it does not respond to user input in any text box. Not even to a click on any text box.
Is there a way I can get the program to do screen update and respond to user input while it is busy?
thanks
Use a BackgroundWorker to perform intensive work (rather than using the UI thread):
VB.NET BackgroundWorker Use
How To Update Controls Using BackgroundWorker in VB.NET
If you need finer grain control then create and manage your own threads: Multithreaded Applications (but the BackgroundWorker would probably meet your needs).
You'll probably need to move the heavy calculation and communication to a separate thread. In other words, it sounds like you may need to do some multithreading.
From the description of the problem, it sounds like the GUI updates and the calculation are performed in a single thread, therefore, when the heavy calculations are taking up all the computing resources, there's no computing resources to update (or respond to) the GUI.
An approach to take in these types of situation is to start a new thread with computation intensive (or potentially blocking operation such as I/O) processing in a separate thread, allowing the GUI to stay alive on the main thread.
Microsoft seems to have an introduction to multithreaded applications in Visual Basic, using the facilities provided in the .NET framework, so that might be a good starting point.
This question is tagged VBA and I will respond accordingly. If the tag is wrong then this answer can be disregarded.
Is there a way I can get the program to do screen update
The DoEvents statement will force a screen update.
Sometimes DoEvents is not enough. An alternative is proposed here.
Add the following line at the top of your module (outside of your function):
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Then add this line in place of, or in addition to, DoEvents:
Sleep 1 'This will pause execution of your program for 1 ms
You might try increasing the length of time you pause the program using sleep if 1 ms doesn't work.
and respond to user input while it is busy?
This is not possible in VBA.
An interesting feature, I have seen in jDownloader software is any links I copy in the browser window (i.e., Ctrl+c), the copied content links automatically appears ( i.e., with out me actually pasting it) in their UI and starts downloading the content from the links, if they are valid.
I would like to program the same but am puzzled as how to access the variable to which OS copies. Please share your ideas.
Thanks.
Adam Robinson's answer is on the right track, but is not entirely correct. I'm going to try and provide the "long" version (in contrast to his "short" version), and explain along the way where/why I think the solution that he proposes falls short of achieving your ultimate goal.
As the documentation he links to explains, there are three different ways of monitoring changes to the Windows clipboard, each with their own caveats:
Creating a clipboard viewer window that hooks into the clipboard viewer chain and receives notification messages when the contents of the clipboard have been changed by the user. (Available on all versions of Windows, but generally more difficult to code and thus discouraged for newer applications that don't have a specific need for its features.)
Querying the clipboard sequence number, which is a 32-bit value that changes each time the clipboard's contents are changed. Your program calls the Windows API function GetClipboardSequenceNumber once and caches its value, then each time you want to check if the clipboard's contents have changed, you call that same function again and compare its return value to the value you've cached. There are two important caveats here:
This function is only available in Windows 2000 and newer. This is not likely to be a problem if you're writing .NET apps, as versions of the Framework as early as 3.0 dropped W2K support.
This is not a notification method, and you should not call this function repeatedly in a polling loop. That means that you have to manually call the appropriate function and compare the clipboard sequence number. You cannot use this method if you want to "listen in" and be immediately notified whenever the clipboard's contents change, as you describe in your question. The documentation is very explicit here:
This method is more suitable to programs which cache results based on the current clipboard contents and need to know whether the calculations are still valid before using the results from that cache. Note that this is a not a notification method and should not be used in a polling loop. To be notified when clipboard contents change, use a clipboard format listener or a clipboard viewer.
Creating a clipboard format listener, which registers to be notified whenever the clipboard's contents change. This is the ideal solution in your case, because it avoids the complexities of creating a clipboard viewer window (option 1), but also allows you listen in and be notified each time the clipboard's contents are changed (in contrast to option 2).
The problem is that this is only available under Windows Vista and later. If you still have any need to target Windows XP (as most of us do), this is really not an option for you.
Therefore, from the example you provide in the question, it sounds to me like the only option available to you is option 1, creating a clipboard viewer window. The documentation goes into the gory details of how you'd set this up using the SetClipboardViewer function and listening for the WM_DRAWCLIPBOARD and WM_CHANGECBCHAIN messages. Getting this to work right can be a difficult task to do on your own, but fortunately for us .NET developers, others have already done the hard work for us. ("Others", I say, despite having been one of those others myself.)
This article on CodeProject is a good example. It implements three different types of hooks: a mouse hook, a keyboard hook, and a clipboard hook. The only thing you're interested in is the clipboard hook, but you can just add a reference to the DLL in your project to start using its functionality immediately.
If you are interested in the internals of how this works and want to try coding it up yourself, this article appears to be a fantastic description of the specific steps involved.
Use the My.Computer.Clipboard.GetText() function
Also see the msdn page
Check out this MSDN link regarding the clipboard. In particular, this link's anchor should take you to the section of the document about monitoring the clipboard contents.
The short version is that you can monitor either by polling for the sequence number and checking to see if it has changed, or you can register to listen for changes for specific clipboard contents formats. Note that the latter is only available on Vista and above, so you depending on your target platform you may have to stick with polling.
In order to use these functions, you'll have to declare a P/Invoke to the unmanaged function. Here's the PInvoke.net page on the GetClipboardSequenceNumber function, though the declaration here is C#, not VB.NET. The VB.NET syntax should be (I don't have VS in front of me to check):
<DllImport("user32.dll")>
Public Shared Function GetClipboardSequenceNumber() as UInt32
End Function
When debugging a VB6 application, I have noticed that the VB6 IDE keeps any libraries loaded if they were used by the application being debugged. The library remains loaded between debugging sessions. This interferes with my debugging because unfortunately, one of our libraries (written in delphi) keeps state around in global variables and has significant initialization/termination logic.
Simplified example of the problem: I have a foo.dll with a counter inside it. I access this counter with the following declares in VB6:
Public Declare Function GetCounter Lib "foo.dll" () As Long
Public Declare Function IncrementCounter Lib "foo.dll" () As Long
The problem in this case is that the counter is not reset when I start a new debugging session. I would rather not write application or library logic to take this "recycled library state" scenario into account. I want to be able to start a debugging session with a clean slate.
Currently I force a library unload by restarting the VB6 IDE. Is there a better way?
edit: I played around a bit with invoking kernel32.dll functions to unload/reload libaries from the immediate window; this turned out to only be a good way to crash the IDE or cause random behavior. I should have expected that as the IDE has no way of knowing that it's original handle for the library has become invalid.
I have accepted AngryHacker's answer as I am now convinced that restarting vb6.exe is the only way to start a VB6 debugging session with a completely clean slate.
I've struggled with that for years back in the day, particularly when coding ActiveX DLLs for use with IIS sites.
The only real antidote I found was to keep the library loaded in a separate VB6 instance (assuming you have the control of the source). That way you could simply press the Stop button on the toolbar and the library would no longer be loaded.
You should look at a few things:
Make sure you are disposing of any class references by setting your local or global variables = nothing when your application exits.
When debugging, NEVER hit the end/stop debugging button. This just pulls the rug out from under the code and can sometimes leave things hanging in memory.
Don't use the End command in your application exit code (see point #2).