BeginInvoke
-
I can't find the equivalent to PostMessage in Windows Forms. I'm currently using BeginInvoke, as it's much like it, but then I get memory leaks, since I ignore the AsyncResults. What should I do with them? Store them in a queue which I walk through later to see if the Completedflag is set and can then safelly call endinvoke? Thanks in advance
-
I can't find the equivalent to PostMessage in Windows Forms. I'm currently using BeginInvoke, as it's much like it, but then I get memory leaks, since I ignore the AsyncResults. What should I do with them? Store them in a queue which I walk through later to see if the Completedflag is set and can then safelly call endinvoke? Thanks in advance
You won't get memory leaks if you ignore
AsyncResult
s. .NET is GC'd. More than likely you're not usingControl.InvokeRequired
andControl.Invoke
to call methods and get/set properties on controls created in a different thread. This is a common problem. When you comunicate with a control that was created on a different thread (the UI thread), you must use theISynchronizeInvoke
impementation that every control inherits fromControl
. This makes sure that communciate with the control happens in the UI thread. If you wantPostMessage
, why not just P/Invoke it? If you read the forms, we're continually telling people to P/InvokeSendMessage
to send the message immediately, but P/InvokingPostMessage
is really no different. It would just look like this:[DllImport("user32.dll")]
private static extern bool PostMessage(
IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int msg,
IntPtr wParam,
IntPtr lParam);If you need to pass a struct or reference to a struct or something, instead of marshaling the struct yourself and passing it as an
IntPtr
, you could overloadPostMessage
like so:[DllImport("user32.dll")]
private static extern bool PostMessage(
IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int msg,
int wParam, // DON'T NEED - SET TO 0
ref LVITEM lvItem);Of course, you'd need to declare a managed
LVITEM
struct (can be named whatever you like, though) that would marshal correctly.Microsoft MVP, Visual C# My Articles
-
You won't get memory leaks if you ignore
AsyncResult
s. .NET is GC'd. More than likely you're not usingControl.InvokeRequired
andControl.Invoke
to call methods and get/set properties on controls created in a different thread. This is a common problem. When you comunicate with a control that was created on a different thread (the UI thread), you must use theISynchronizeInvoke
impementation that every control inherits fromControl
. This makes sure that communciate with the control happens in the UI thread. If you wantPostMessage
, why not just P/Invoke it? If you read the forms, we're continually telling people to P/InvokeSendMessage
to send the message immediately, but P/InvokingPostMessage
is really no different. It would just look like this:[DllImport("user32.dll")]
private static extern bool PostMessage(
IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int msg,
IntPtr wParam,
IntPtr lParam);If you need to pass a struct or reference to a struct or something, instead of marshaling the struct yourself and passing it as an
IntPtr
, you could overloadPostMessage
like so:[DllImport("user32.dll")]
private static extern bool PostMessage(
IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int msg,
int wParam, // DON'T NEED - SET TO 0
ref LVITEM lvItem);Of course, you'd need to declare a managed
LVITEM
struct (can be named whatever you like, though) that would marshal correctly.Microsoft MVP, Visual C# My Articles
Thank you very much for your answer. Although I don't agree on your discussion, I'll use the code you gave me. I tested calling BeginInvoke(Nada) a hundred thousand times and then GC.Collect(); The memory footprint after the collection was over a hundred megs. ??? And the reason I ask is that I do use BeginInvoke, but am not satisfied with it. And Invoke is no option since it causes deadlocks in my case. (The UI is updated from a background process.)
-
Thank you very much for your answer. Although I don't agree on your discussion, I'll use the code you gave me. I tested calling BeginInvoke(Nada) a hundred thousand times and then GC.Collect(); The memory footprint after the collection was over a hundred megs. ??? And the reason I ask is that I do use BeginInvoke, but am not satisfied with it. And Invoke is no option since it causes deadlocks in my case. (The UI is updated from a background process.)
Doesn't really matter if you don't agree with me - it's documented in the .NET Framework SDK. I suppose, then, that you disagree with Microsoft. I didn't say that ignoring the
AsyncResult
s doesn't incur a certain performance hit with memory consumption, I said it didn't incur any memory leaks. There is a difference. The very fact that the GC was able to collect the unused references proves that the objects where indeed tracked. The GC would've collected them eventually. Memory leaks are when memory is lost and unreferenced, so it cannot be freed again, like when a variable references an alloc'd region of memory which is not freed. Once that variable goes out of scope it's practically impossible to free that memory again. The fact remains that calling methods or setting properties (often getting as well) on controls from a different thread may cause problems. This is what's documented well in the .NET Framework if you read the right topics. Sometimes things may work. Other times they may not. Often times it is certain functionality that doesn't work as expected. It call comes down to the synchronization of threads, like it or not.Microsoft MVP, Visual C# My Articles