.NET and C# Notes — Falling Back from async/await, C++ DLL Marshalling, Saving a WPF Control as PNG
Contents
Three notes from building a Windows app in 2015, merged into one page.
Writing it with async/await, then falling back to 4.0
A Windows app came up. Since .NET 4.5 introduced the async syntax, I decided to build it on 4.5.2 while I was at it. It is remarkably convenient.
async and await are the whole story. In a UI program they
make synchronizing between a background thread and the main thread trivial.
Here is the login flow: take an id and password, authenticate against the server.
| |
The whole login completes straight out of the client event with no separate thread
synchronization. No Invoke, no Dispatcher.
Then testing started, and not many of the target PCs had .NET Framework 4.5 installed.
So it got rewritten for 4.0 using BackgroundWorker. Miserable. At least it was only a
three-screen program.
The lesson: convenient syntax matters less than checking the runtime version on the machines you are deploying to.
Passing LPCTSTR from C# into a C++ DLL
An example of calling a C++ dll from C#.
The C++ side
| |
| |
The C# side
| |
CallingConvention = CallingConvention.Cdecl and [MarshalAs(UnmanagedType.LPWStr)] are
the two that matter. Miss either one and the call breaks or the string arrives garbled.
Receiving a string back from C++
Take it as an IntPtr and convert.
| |
Skipping the free leaks.
Saving a WPF control as PNG
I was about to reach for System.Drawing as usual, but WPF already has this built in.
| |
RenderTargetBitmap is the key piece — it renders the on-screen control straight to a
bitmap.
Summary
- async/await removes most UI thread synchronization, but check the target runtime first
- Calling a C++ dll needs
CallingConvention.CdeclplusMarshalAs(UnmanagedType.LPWStr) - Always release a returned
IntPtrwithMarshal.FreeHGlobal - Capture a WPF control with
RenderTargetBitmap