I am getting the below error and call stack at the same time everyday after several hours of application use. Can anyone shed some light on what is happening?
System.InvalidOperationException: BufferedGraphicsContext cannot be disposed of because a buffer operation is currently in progress.
at System.Drawing.BufferedGraphicsContext.Dispose(Boolean disposing)
at System.Drawing.BufferedGraphicsContext.Dispose()
at System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
at System.Drawing.BufferedGraphicsContext.Allocate(IntPtr targetDC, Rectangle targetRectangle)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.MenuStrip.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
There is a very long MSDN forums discussion of this error here. In most cases the error is apparently associated with either:
An underlying OutOfMemory problem, which manifests as the BufferedGraphicsContext exception, possibly due to a framework bug.
A GDI object leak (creating GDI objects and not disposing them).
I recall seeing this error myself a year or so ago, and it was definitely associated with a memory problem that made our app fill up all available VM after a long run, so #1 agrees with what I have observed.
a shot in the dark - are you painting from multiple threads? If you are doing painting related work, do it on the GUI thread or synchronize your code carefully.
I know this question is old, but i had the same problem and found out, that it only showed up, when i used multiple controls which implemented manual double buffering.
For me, i found the problem at this point:
BufferedGraphicsContext _BackbufferContext = BufferedGraphicsManager.Current;
So all my controls used the Current context, which i assume is always the same.
After i replaced it by
BufferedGraphicsContext _BackbufferContext = new BufferedGraphicsContext();
everything works like wanted.
I hope this is a little bit helpfull.
Related
I write simple windows c program to display the bitmap at the place where the left mouse button is pressed. At the first time when I click my left mouse button, the bitmap appears. But on the second time on words the bitmap is not getting displayed on the place where I made a left mouse click.
Here is my code.........
LRESULT CALLBACK myHandler(HWND hw, UINT m, UINT mextra, long co_ord)
{
HDC hdc, hmemdc;
PAINTSTRUCT ps;
HBITMAP hbmp;
RECT r;
HGDIOBJ holdbmp;
int x, y;
switch(m)
{
case WM_LBUTTONDOWN:
hdc = BeginPaint(hw,&ps);
hmemdc = CreateCompatibleDC(hdc);
hbmp = LoadBitmap(h, MAKEINTRESOURCE(IDB_BITMAP1));
holdbmp = SelectObject(hmemdc, hbmp);
x = LOWORD(co_ord);
y = HIWORD(co_ord);
BitBlt(hdc, x, y, 190, 220, hmemdc, 0, 0, SRCCOPY);
EndPaint(hw,&ps);
SelectObject(hmemdc, holdbmp);
DeleteObject(hbmp);
DeleteDC(hmemdc);
DeleteDC(hdc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hw,m,mextra,co_ord);
}
return 0L;
}
The code is wrong about seven different ways from Sunday. Even after the changes you've made in response to WhozCraig's comments, it is still wrong.
For starters, the only place you are allowed to call BeginPaint and EndPaint is in response to a WM_PAINT message. You are trying to call these functions in response to a WM_LBUTTONDOWN message. That cannot work. What you'll want to do is trigger a WM_PAINT message from within your WM_LBUTTONDOWN message handler, which you can do by calling the InvalidateRect() function, passing your window handle and NULL for the rectangle to invalidate (to invalidate your entire window). Then, inside of the WM_PAINT message handler, you can call BeginPaint/EndPaint and do your drawing. If you want the drawing to be different depending on whether the left mouse button is down, you can either set a flag inside of the WM_LBUTTONDOWN message handler and test the value of that flag inside of your WM_PAINT message handler, or you can use something like GetKeyState to determine whether the mouse button is down (VK_LBUTTON).
You are also leaking GDI objects because you are not correctly releasing/destroying them. A bitmap that has been loaded with LoadBitmap needs to be destroyed by calling DeleteObject. (However, loading a bitmap repeatedly inside of a WM_PAINT message handler will lead to poor performance. Instead, prefer to load the bitmap a single time in response to the WM_CREATE message, cache its handle in a global or class-level variable, use it when necessary, and destroy the bitmap via that handle in response to the WM_DESTROY message.)
The LOWORD and HIWORD macros should never be used for extracting cursor coordinates. These are liable to return the wrong result on multiple monitor systems. Instead, you should use GET_X_LPARAM and GET_Y_LPARAM. This is specifically mentioned in the MSDN documentation for the WM_LBUTTONDOWN message. Always read the documentation for things you are unfamiliar with!
Finally, the signature for your window procedure is also completely wrong. I have no idea where you got that signature, but not only do you have non-standard parameter names that obscures the actual meaning of those arguments, but you have the wrong types. A window procedure looks like this:
LRESULT CALLBACK myHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
...
}
It is extremely difficult to learn Windows API programming by just hacking around, especially if you aren't disciplined about reading the MSDN documentation. If you really want to learn it, consider purchasing a book, like Charles Petzold's classic Programming Windows, 5th edition (yes, you need the 5th edition, not a newer edition).
I am fiddling with wndprocs and WinSpy++ and i stumbled upon a strange thing with calc.exe.
It appears to lack a WndProc.
Here is my screenshot: a test program I made, the WinSpy++ window,, showing N/A, and the culprit.
Maybe the tool is a bit outdated, but the empirical evidence proves no WndProc is there.
I don't know if this is by design(this would be strange), or if I am missing something...
Here is referenced code:
Function FindWindow(title As String) As IntPtr
Return AutoIt.AutoItX.WinGetHandle(title)
End Function
Function GetWindowProc(handle As IntPtr) As IntPtr
Return GetWindowLong(handle, WindowLongFlags.GWL_WNDPROC)
End Function
In short (about your code): GetWindowLong() fails because you're trying to read an address in target process address space.
EXPLANATION
When GetWindowLong() returns 0 it means there is an error, from MSDN:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Check Marshal.GetLastWin32Error() and you probably see error code is ERROR_ACCESS_DENIED (numeric value is 0x5).
Why? Because GetWindowLong() is trying to get address (or handle) of window procedure (not in your code, but in target process, in theory it may even be default window procedure but I never saw an application main window that doesn't hanle at least few messages). You may use this trick (but I never tried!) to see if a window is using default procedure (you have an address or not), I don't know...someone should try.
Now think what WNDPROC is:
LRESULT (CALLBACK* WNDPROC) (HWND, UINT, WPARAM, LPARAM);
An address (valid in process A) is not callable in process B (where it makes no sense at all). Windows DLLs code segments are shared across processes (I assume, I didn't check but it's reasonable in the game between safety and performance).
Moreover CallWindowProc(NULL, ...) will understand that NULL as a special value to invoke window procedure for that window class (on HWND owner). From MSDN:
...If this value is obtained by calling the GetWindowLong function ...the address of a window or dialog box procedure, or a special internal value meaningful only to CallWindowProc.
How Microsoft Spy++ does it (and maybe WinSpy++ does not)? Hard to say without WinSpy++ source code. For sure it's not such easy like GetWindowLong() and right way should involve CreateRemoteThread() and to do LoadLibrary() from that but both Microsoft Spy++ and WinSpy++ source code aren't available (AFAIK) for further inspection...
UPDATE
WinSpy++ inspection/debugging is pretty off-topic with the question (you should post a ticket to developers, your source code may fail for what I explained above, you should - always - check error codes) but we may take a look for fun.
In InjectThread.c we see it uses WriteProcessMemory + CreateRemoteThread then ReadProcessMemory to read data back (not relevant code omitted):
// Write a copy of our injection thread into the remote process
WriteProcessMemory(hProcess, pdwRemoteCode, lpCode, cbCodeSize, &dwWritten);
// Write a copy of the INJTHREAD to the remote process. This structure
// MUST start on a 32bit boundary
pRemoteData = (void *)((BYTE *)pdwRemoteCode + ((cbCodeSize + 4) & ~ 3));
// Put DATA in the remote thread's memory block
WriteProcessMemory(hProcess, pRemoteData, lpData, cbDataSize, &dwWritten);
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pdwRemoteCode, pRemoteData, 0, &dwRemoteThreadId);
// Wait for the thread to terminate
WaitForSingleObject(hRemoteThread, INFINITE);
// Read the user-structure back again
if(!ReadProcessMemory(hProcess, pRemoteData, lpData, cbDataSize, &dwRead))
{
//an error occurred
}
Window procedure in "General" tab and in "Class" tab differs (in "Class" tab it correctly display a value). From DisplayClassInfo.c:
//window procedure
if(spy_WndProc == 0)
{
wsprintf(ach, _T("N/A"));
}
else
{
wsprintf(ach, szHexFmt, spy_WndProc);
if(spy_WndProc != spy_WndClassEx.lpfnWndProc)
lstrcat(ach, _T(" (Subclassed)"));
}
//class window procedure
if(spy_WndClassEx.lpfnWndProc == 0)
wsprintf(ach, _T("N/A"));
else
wsprintf(ach, szHexFmt, spy_WndClassEx.lpfnWndProc);
As you see they're different values (obtained in different ways). Code to fill spy_WndProc is in WinSpy.c and GetRemoteWindowInfo.c. Extracted code from GetRemoteInfo() in WinSpy.c:
GetClassInfoEx(0, spy_szClassName, &spy_WndClassEx);
GetRemoteWindowInfo(hwnd, &spy_WndClassEx, &spy_WndProc, spy_szPassword, 200);
Now in GetRemoteWindowInfo() we see a call to GetClassInfoExProc (injected in the other process):
pInjData->wndproc = (WNDPROC)pInjData->fnGetWindowLong(pInjData->hwnd, GWL_WNDPROC);
pInjData->fnGetClassInfoEx(pInjData->hInst,
(LPTSTR)pInjData->szClassName, &pInjData->wcOutput);
As you can see (please follow using source code) wcOutput is what is displayed in "Class" tab and wndproc what is displayed in "General" tab. Simply GetWindowLong() fails but GetClassInfoEx does not (but they do not necessarily retrieve same value because (if I'm not wrong) what you have in WNDCLASSEX is what you registered with RegisterClassEx but what you get with GetWindowLong() is what you hooked with SetWindowLong().
You are right. It does not have a WndProc(...) function. It is just simply using a DlgProc to process the dialog events. I now this as I have written 'server/thin client' code in C/C++ to capture direct calls into windows API functions like WndProc(...). Any Windows GUI function really - BeginPaint(...) as an example. I used CALC.EXE as a test and executable runs on server while GUI calls are relayed/returned to/from the thin client. Have only tested calc.exe versions thru Vista. There is a chance the newer versions have been 'programmed' differently - meaning not using Win32 SDK. But, even MFC is just a shell to the Win32 SDK,
I get this exception in my application.
I have found links discussing it on the web but nothing indicating how to track it down and/or workaround it.
Please do not reply with links from the internet.
Please reply with strategies of tracking the source.
Please reply with workarounds if you found them.
Source: PresentationCore
Message: Exception from HRESULT: 0x88980406
Stack Trace:
at System.Windows.Media.Composition.DUCE.Channel.SyncFlush()
at System.Windows.Interop.HwndTarget.UpdateWindowSettings(Boolean enableRenderTarget, Nullable`1 channelSet)
at System.Windows.Interop.HwndTarget.UpdateWindowPos(IntPtr lParam)
at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
This is old, but I will answer anyways, since I had the same issue that I just resolved.https://stackoverflow.com/a/18003004/1415307
Basically, my issue with this error came down to an outdated video card driver. After updating to the newest driver, the issue has been resolved.
In my case it turned out the application in question was already pressing up on memory limits of its specced hardware. Any time I added code that used a decent amount of memory this would crop up.
I ended up using a MemoryFailPoint mechanism when I implemented a feature that placed processing an image buffer on another thread.
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.memoryfailpoint
First implementation did the trick but after many tries QA caused a OOM bomb.
So I implemented a MemoryFailPoint() with GC.Collect() loop (hackish I know...but sometimes...get er done).
The main things I learned were:
This is a really bad bug in WPF.
You only have to worry about it if you have truly consumed an inordinate amount of memory.
With Microsoft's excellent help, we just solved a SyncFlush problem that has plagued us for more than a year. It turns out that we were creating multimedia timers in native code, but we weren't freeing them every time. More specifically, we called timeBeginPeriod and timeEndPeriod, but we called begin more times than end, thus creating a resource leak. The WPF rendering thread needs to use those timers, but we exhausted a limited supply of them (perhaps 65k). The result was that the rendering thread stopped rendering and either hung or caused a crash. Watch out for timers!
We are using the WPF FormattedText object to determine text size in a service that grabs the latest news headlines from an RSS feed. The text retrieved needs to be in a specified canvas size. The service runs the code every 10 seconds and uses up to 2 threads if one takes longer than that. I'm using TaskFactory (which I've overridden the LimitedConcurrencyLevelTaskScheduler to limit to the amount of threads I specified).
This works great, except after several days (the length is variable), we start to get the following exceptions. The same code was working fine before we started using TPL to make it mult-threaded.
I need help figuring out what this is caused by. A few thoughts I'm looking into are: thread collisions holding on to a TTF file, memory issue, the dispatcher (see the stack trace) isn't playing nicely with the TaskFactory, other??
We don't have good profiling setup, but we've looked at the TaskManager when the exception is occurring and memory usage looks normal.
My next attempt is to use the TextBlock object and see if the exception is avoided.
Error Message: The system cannot find the file specified
Error Source: WindowsBase
Error Target Site: UInt16 RegisterClassEx(WNDCLASSEX_D)
Exception Stack Trace:
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.Dispatcher.get_CurrentDispatcher()
at System.Windows.Media.TextFormatting.TextFormatter.FromCurrentDispatcher(TextFormattingMode textFormattingMode)
at System.Windows.Media.FormattedText.LineEnumerator..ctor(FormattedText text)
at System.Windows.Media.FormattedText.DrawAndCalculateMetrics(DrawingContext dc, Point drawingOffset, Boolean getBlackBoxMetrics)
at System.Windows.Media.FormattedText.get_Metrics()
at
(my method using the FormattedText, which is in a loop)
private static Size GetTextSize(string txt, Typeface tf, int size)
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}
EDIT: so far I've tried placing a lock around the code that calls this function, and calling it inside the CurrentDispatcher.Invoke method like so:
return (Size)Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}));
EDIT: I've found links to others having similar, but not the exact problem.
http://www.eggheadcafe.com/software/aspnet/31783898/problem-creating-an-bitmapsource-from-an-hbitmap-in-threaded-code.aspx ~having a similar problem, but no answers
System.Windows.Media.DrawingVisual.RenderOpen() erroring after a time ~having a similar problem, but no answers
http://connect.microsoft.com/VisualStudio/feedback/details/361469/net-3-5-sp1-breaks-use-of-wpf-under-iis# ~ similar exception, but we're not using 3.5SP1 or IIS 7.
I've also submitted this through the Microsoft Connect site (please vote for it if you are having a similar problem).
https://connect.microsoft.com/WPF/feedback/details/654208/wpf-formattedtext-the-system-cannot-find-the-file-specified-exception-in-a-service
EDIT: Response from Microsoft:
"WPF objects need to be created on Dispatcher threads, not thread-pool threads. We usually recommend dedicating a thread to run the dispatcher loop to service requests to create objects and return
them frozen. Thanks, WPF Team" ~ How would I implement this?
EDIT: final solution thanks to NightDweller
if(Application.Current == null) new Application();
(Size)Application.Current.Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
...});
EDIT: When I deployed the change (new Application();), I got an error logged " Cannot create more than one System.Windows.Application instance in the same AppDomain."
Error Source: PresentationFramework
Error Target Site: Void .ctor()
A shot in the dark:
The stack trace seems to show that WPF does not find a Dispatcher in the thread executing GetTextSize, so it has to create a new one, which involves creating a handle to a window.
Calling this every 10 seconds means 8'640 threads, thus windows per day. According to Mark Russinovich, there is a limit of 32 K windows per session, which may explain the error in RegisterClassEx.
An idea to overcome this is to read the current dispatcher from your main thread and set it in your tasks.
Edit:
I had another look and it looks like one cannot set the Dispatcher of a thread (it's created automatically).
I'm sorry, I am unable to understand what is going on here.
In order to compute the text size, WPF needs a FormattedText instance, which is stored as a member of the Dispatcher class. The existing Dispatchers are stored in a list of weak references. Each one is associated with a specific thread.
Here, it looks like new Dispatcher instances are created many, many times.
So, either the calling thread is new or memory is quite low and the weak references have been discarded.
The first case (new thread) is unlikely as the task scheduler uses the thread pool, which has about 25 threads per core (if I remember correctly), which is not enough to deplete the pool of ATOMs or windows.
In the second case, the depletion of resource is unlikely as the HwndWrapper is IDisposable and the Dispose method takes care of freeing the registered class.
As you already know from the info you provided, All UI elements (FormattedText is one) have to be created on the UI thread.
The code you are looking for is:
return (Size)Application.Current.Dispatcher.CurrentDispatcher.Invoke(new Func<Size>(() =>
{
FormattedText ft = new FormattedText(txt, new CultureInfo("en-us"), System.Windows.FlowDirection.LeftToRight, tf, (double)size, System.Windows.Media.Brushes.Black, null, TextFormattingMode.Display);
return new Size { Width = ft.WidthIncludingTrailingWhitespace, Height = ft.Height };
}));
Notice the Application.Current - you want the "Application" dispatcher which is the dispatcher for the UI thread in WPF applications.
Your current code actually creates a dispatcher for the current thread so you didn't really change the executing thread (see here regarding the dispatcher)
Have you renamed anything? If yes, check that link: WPF Prism: Problem with creating a Shell
I'm building a Windows Phone 7 application that uses isolated storage. The code works most of the time but I keep getting IsolatedStorageExceptions randomly:
{"An error occurred while accessing IsolatedStorage."}
There are no further details about the reason for the exception. Here is the stack trace:
at System.IO.IsolatedStorage.IsolatedStorageFile.DeleteFile(String file)
at MyApp.Core.Data.WindowsPhoneFileRepository.DeleteFile(String name)
at MyApp.Core.Domain.ThingService.SaveThing(Thing Thing)
at MyApp.Core.Domain.TrackedThingService.PersistThingLocally(TrackedThing Thing)
at MyApp.Ui.ViewModels.TrackViewModel.<.ctor>b__3(Thing Thing)
at GalaSoft.MvvmLight.Command.RelayCommand`1.Execute(Object parameter)
at GalaSoft.MvvmLight.Command.EventToCommand.Invoke(Object parameter)
at System.Windows.Interactivity.TriggerAction.CallInvoke(Object parameter)
at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter)
at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs)
at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs)
at System.Windows.Controls.Primitives.ButtonBase.OnClick()
at System.Windows.Controls.Button.OnClick()
at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)
The file exists. I place all my IsolatedStorage uses inside using blocks so I shouldn't have the file open anywhere.
What could be causing this?
How I can I get more details about the cause of the exception?
Using blocks are currently not guaranteed to flush/close streams in WP7.
Close all files/streams explicitly until the SDK reaches the point you can actually trust it! :)
I would specifically check to make sure that you've closed all readers and writers to anything within the File that you are trying to delete. I'm not saying that will definately fix it, but rather not being able to delete files that do exist tend to be caused by open files.
It should not be overlooked that the WP7 is still in Beta (you've updated from the CTP to the Beta version right?).
Consider creating a very simple application that manipulates the Isolated storage in the way your main application is to see if you can create a small Repo of the problem. Having done that send it to Microsoft so they can take a look at it.
I faced the same problem.
I checked carefully and found a place where I didn't close the FileStream. Closing it solved the problem for me.