Generic GDI+ Error - winforms

I have a Form being launched from another form on a different thread. Most of the time it works perfectly, but I get the below error from time to time. Can anyone help?
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
at System.Drawing.Icon.ToBitmap()
at System.Windows.Forms.ThreadExceptionDialog..ctor(Exception t)
at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t)
at System.Windows.Forms.Control.WndProcException(Exception e)
at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
at System.Windows.Forms.Form.ShowDialog()

The user has to be able to see multiple open accounts simultaneously, right? So you need multiple instances of a form?
Unless I'm misreading something, I don't think you need threads for this scenario, and I think you are just introducing yourself to a world of hurt (like these exceptions) as a result.
Assuming your account form is called AccountForm, I'd do this instead:
Dim acctForm As New AccountForm()
acctForm.Show()
(Of course you'll have your own logic for that ... ) I might even put it in the ShowForm method so that I could just update my caller thusly:
ShowForm()
And be done. Now all of this assumes that you've encapsulated the AccountForm nicely so that each instance has its own data, and they don't share anything between instances.
Using threads for this is not only overkill, but likely to introduce bugs like the exception at the top. And my experience in debugging multi-threaded WinForms apps has shown that these bugs are often very difficult to replicate, and extremely tricky to find and fix. Oftentimes, the best fix is to not multithread unless you absolutely, positively have to.

Can you elaborate what you are trying to do here?
If you are trying to show a Form from a different thread than the UI thread then refer to this question:
My form doesn't properly display when it is launched from another thread

The application is an Explorer-Type customer management system. An account form is launched from the "Main" explorer form on a separate background thread. We do this because the user needs to be able to have multiple accounts open at the same time.
We launch the form using this code:
Thread = New Thread(AddressOf ShowForm)
Thread.SetApartmentState(ApartmentState.STA)
Thread.IsBackground = True

Related

WPF Binding Exception

We have a WPF application using Prism 6.0 which have different screens that show collections. Many of these views are loaded in the startup and shown as necessary.
Sporadically, we are getting an exception in the startup. The exception call-stack does not give any useful information (except that it is a cross thread collection access issue) and we are finding it difficult to find the root cause. The exception is as below
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Collections.ObjectModel.Collection`1.get_Item(Int32 index)
at System.Collections.ObjectModel.ReadOnlyCollection`1.System.Collections.ICollection.CopyTo(Array array, Int32 index)
at System.Collections.ArrayList.InsertRange(Int32 index, ICollection c)
at System.Collections.ArrayList.AddRange(ICollection c)
at System.Collections.ArrayList..ctor(ICollection c)
at System.Windows.Data.ListCollectionView.<RefreshOverride>b__1_0()
at MS.Internal.Data.SynchronizationInfo.AccessCollection(IEnumerable collection, Action accessMethod, Boolean writeAccess)
at System.Windows.Data.BindingOperations.AccessCollection(IEnumerable collection, Action accessMethod, Boolean writeAccess)
at System.Windows.Data.ListCollectionView.RefreshOverride()
at System.Windows.Data.CollectionView.RefreshInternal()
at System.Windows.Data.CollectionView.RefreshOrDefer()
at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
at System.Windows.Data.CollectionView.ProcessChangeLog(ArrayList changeLog, Boolean processAll)
at System.Windows.Data.CollectionView.ProcessInvoke(Object arg)
at MS.Internal.Data.DataBindOperation.Invoke()
at MS.Internal.Data.DataBindEngine.ProcessCrossThreadRequests()
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
Is there any way to which collection (at least the type of collection elements) is causing this issue or any way to find the root cause?
Any ideas are welcome!
thank you
This exception is usually thrown when the index used to access the collection is less than zero or equal to or greater than the collection's Count.
A cross-thread exception would usually be of type NotSupportedException.
You must ensure that the index is within the range.
To find the exact location you must go to the Debug menu and enable the debugger to break on all exceptions and then run you application in debug mode:
Press Ctrl+Alt+E and tick the "Common Language Runtime Exceptions" check box
Run in debug mode to make the program halt at the line of origin (in case of proper exception handling)
From your exception message it looks like the stack trace is generated from a release build.
In this case make sure you publish the PDB files too (debug symbols). This will allow the exception stack trace to include line numbers.
Another option is to review all your index based collection access (read) and guard against an index out of range (it should be standard in production code). You could use the occasion to do this for index based write access too. You can use the search tool to locate indexers in your solution.
Even if you include PDB files or use the debug mode to identify the line of origin, you should consider to review your code base for other brittle index based collection access with the help of the search tool. And maybe add a rule to your coding guide to force developers to check the collection bounds before accessing it by index.

WindowInteropHelper.Handle — do I need to release it?

In WPF I'm getting IntPtr handle using this code:
IntPtr mainWindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle
When I finish using this handle, do I need to release it in anyway (e.g. using Marshal.FreeHGlobal() method) ?
EDIT: I was thinking about Marshal.FreeHGlobal(), not Marshal.Release(), sorry!
This is not in any way related to COM, Marshal.Release() does not apply. You simply get a copy of the native window handle, it does not have to be released. You need to stop using the handle when the window is destroyed. Signaled by the Window.Close event.

Windows: two threads handling messages?

I want to have two threads to handle windows messages. One for key/mouse input in the client area (this thread also takes care of game logic) and one for the rest because I am making a game and some messages cause DefWindowProc() to block (thus freezing the game).
How can I achieve this?
Contrary to what Cody wrote, you most definitely can process messages from multiple threads. However, this is not a customizable free-for-all. Rather, windows have thread affinity: each thread will receive the messages sent or posted to windows created by that thread. There's no way to have any window's messages delivered to any other thread.
For your particular situation, why not create a worker thread with its own hidden window and message loop? Any time the main window receives a message you don't want to process in the main thread, post it to the other window, it will be queued to and processed by the worker thread.
You should only need a single thread handling the message queue, which is what Windows already supplies. If you are doing anything which is computationally heavy, you should dispatch it off to a separate thread by creating a new one with CreateThread. If you find you are constantly doing this, then have that thread permanently there but signal it to do work when you need to.
No, all messages need to be processed on a single thread. This single thread is often called the UI thread because it is the one that controls the user interface. Trying to process UI messages on a non-UI thread will just get you into trouble.
However, a common problem is applications that perform long-running, computationally-intensive tasks in response to particular messages. This doesn't work out well because while the code is running inside of the message handler, the application is unable to process other messages (threads can only do one thing at a time), and your UI becomes unresponsive.
The solution is to spin off another thread (or two or however many you need) and delegate the long-running, computationally-intensive tasks off to that thread. You'll still handle the messages on the single UI thread, but inside of the message handlers is where you'll pass off the task to the helper threads. You'll frequently hear this referred to as the "worker thread" or "background thread" pattern.
You can create additional threads using the CreateThread function. You can find a sample here.
In this case, it sounds like the QueueUserWorkItem function might be a simpler option. Sample code:
DWORD CALLBACK ThreadProc(LPVOID p)
{
HWND hWnd = reinterpret_cast<HWND>(p);
for (int i = 0; i < 100000; ++i)
{
// do whatever
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_KEYDOWN: // or whatever message you want to respond to
{
QueueUserWorkItem(ThreadProc, hWnd, WT_EXECUTELONGFUNCTION);
return 0;
}
// process other messages...
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Required reading on Win32 thread pools is here.

Question about making Asynchronous call in C# (WPF) to COM object

Sorry to ask such a basic question but I seem to have a brain freeze on this one! I'm calling a COM (ATL) object from my WPF project. The COM method might take a long time to complete. I thought I'd try and call it asychronously. I have a few demo lines that show the problem.
private void checkBox1_Checked(object sender, RoutedEventArgs e)
{
//DoSomeWork();
AsyncDoWork caller = new AsyncDoWork(DoSomeWork);
IAsyncResult result = caller.BeginInvoke(null, null);
}
private delegate void AsyncDoWork();
private void DoSomeWork()
{
_Server.DoWork();
}
The ATL method DoWork is very exciting. It is:
STDMETHODIMP CSimpleObject::DoWork(void)
{
Sleep(5000);
return S_OK;
}
I had expectations that running this way would result in the checkbox being checked right away (instead of in 5 seconds) and me being able to move the WPF gui around the screen. I can't - for 5 seconds.
What am I doing wrong? I'm sure it's something pretty simple. Delegate signature wrong?
Thanks.
I'm sure you're right about the call to your ATL code getting marshaled to the GUI thread because the ATL code is STA, thereby blocking your GUI thread.
Two solutions:
Rearchitect the ATL portion to be MTA, which may not be feasible, or
Leave the ATL as STA but initially construct the COM object in a thread created for that purpose so it will get a different apartment.
A WPF application actually runs just fine with multiple UI threads, as long as each UI thread has manages its own part of the UI, and the parts are separated by HwndSource. In other words, the second thread that runs part of the UI implements a Win32 HWND which is then embedded in the portion of the UI run by the main thread.
If your COM object isn't itself a GUI object, then it should be very easy to construct it in a separate worker thread and leave it there. Since it is a STA object, all calls will be marshaled to the other thread.
BeginInvoke is still going to execute your call on the same thread, just asynchronously*. You can either create a new Thread object:
Thread comthread = new Thread(new ThreadStart(delegate() { DoSomeWork(); }));
comthread.Start();
or try out .Net 4's new Task library:
Task.Factory.StartNew(() =>
{
DoSomeWork();
});
which are essentially the same thing.**
*A delegate type's BeginInvoke method executes on the same thread as the caller, but in the background. I'm not sure if there are rules regarding what gets executed when, but it's certainly not in the order you want. However, asynchronous methods like BeginRead execute on a special thread separate from the main one.
**There is a slight difference - the Thread method will always create a new Thread object, whereas the Task system has a pool of threads to work with, which is in theory more efficient.
I have done some more thinking and testing about this. There is nothing wrong with the C# code. If the ATL object is an STA object (as it was in my case), it will be called on the main thread, regardless of attempts by the C# code to call it on a worker thread. Changing the ATL object to an MTA object makes it possible to to call it asynchronously.

Launching IE from winforms, can I close IE when my winforms closes?

I have a winforms application, that why someone clicks on a button I need to open up IE to a specific URL.
When someone closes the winforms app, I then need to close IE.
Is this possible? If yes, how?
If you dont have the reference to the old process you used for launching IE, you have to search through the process array returned by System.Diagnostics.Process.GetProcessesByName("IEXPLORE") and kill the specific process.
some samples here.
It would be possible to do that, but it might be a better idea to simply embed Internet Explorer into your application using the WebBrowser control. That way when you close the website you have no chance of closing the whole window when your website opened in a new tab in an existing IE window.
Edit: If you're going to do it anyway, look at the MSDN page on System.Diagnostics.Process.Close
Yes it is possible,
When you call System.Diagnostics.Process.Start() to start the browser, use a specifically created process object. You can later use the process information to kill the process.
However, as Dan Walker mentioned, it might be a better idea to just use the Web Browser control, unless you have specific navigation needs, then it might be more effective to just start and kill IE.
Not sure how you are launching IE, but if you keep a reference to the launched process (or the window handle that was created), you can kill the process (or close the window) when you app exits.
EDIT:
Code to close a window handle is like
Utilities.Utilities.SendMessage(mTestPanelHandle, WM_COMMAND, WM_CLOSE, 0);
if you have a P/Invoke
public const int WM_COMMAND = 0x0112;
public const int WM_CLOSE = 0xF060;
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true,
CallingConvention = CallingConvention.StdCall)]
public static extern int SendMessage(IntPtr hwnd, uint Msg, int wParam, int lParam)
Try this (assuming by WinForms you are using .NET)
Process ieProcess = Process.Start("iexplore", #"http://www.website.com");
// Do work, etc
ieProcess.Kill();
This will only kill the instance you started.

Resources