.Net tips and tricks

  1. Allocating a console in a Windows Forms Application

  2. To allocate a console in a Windows Forms Application, you need to add the following class to your project (or a reference to an assembly that contains this class):

    public class Win32
    {
      [DllImport("kernel32.dll")]
      public static extern Boolean AllocConsole();
      [DllImport("kernel32.dll")]
      public static extern Boolean FreeConsole();
    }

    You will also have to add a using directive:

    using System.Runtime.InteropServices;

    Finally, you allocate the console by making the call Win32.AllocConsole();

  3. Finding C++ memory leaks

    Add the following lines to stdafx.h

    #define CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>

    At the end of execution, call the _CrtDumpMemoryLeaks function and look at its output. The output will say something like:

    Dumping objects ->
    {25} normal block at 0x21449812, 15 bytes long

    This means that the 25 call to the allocator was leaked (never released). To debug it, just put a breakpoint on the allocation routine (_heap_alloc_dbg() in dbgheap.c) and make the breakpoint's hit count 25 (ie. it stops on the 25th hit). Then wait for it to happen, and look at the callstack and you will see who is leaking the memory!

  4. There is no win32 semaphore equivalent in .Net 1.1

    That's right. If you want the win32 counting semaphore functionality you need to write your own or use P/Invoke to use the Win32 semaphore. .Net 2.0 apparently has a semaphore object with the win32 semantics.

  5. Value types can have Finalize() routines but they're never called

    In fact, C# and VB.Net don't allow structs to have destructors, for this reason.

  6. Use EventHandler delegates for your events

    The proper way to do events is always have your events use the standard .Net EventHandler delegate. Similarly, you should pass event params as objects that inherit from EventArgs, and your delegation call should include a pointer to the event source. For an example of how to do this properly (and generically and robustly) look at the Samples/Delegates/RobustEvents project.

  7. Use an EventHandlerList for sources with many events

    If you have a source that has many events, it can get tedious declaring them all in your object. The EventHandlerList class provided by the framework, is the natural solution to to this.

  8. Consider using a flag enum and interface for subscribing to many events

    It can get tedious writing += millions of times to connect a sink to many events provided by a source. Instead, you can handroll a technique where you define an enum EventType with the [Flags] attribute that lists the different events that a source provides (plus an extra enum value for all of them). You also define an interface IEventSink that contains a handler method for each event. Then provide a single Subscribe() or Advise() method on the source that looks like: Advise(IEventSink sink, EventType types). Inside the Advise() method you would use bitwise &'s to see what events this sink is interested in, and += new EventHandler(sink.OnEvent1) where OnEvent1 is the handler defined in the interface for the EventType Event1 in the enum.

  9. Asynchronous delgate threads are background threads

    This means an application can exit before they are complete (unlike normal threads). I believe this is because they come from the application thread pool.

  10. Thread pools have 25 threads per CPU so watch out for exhaustion

    If you fire a lot of aynchronous calls in your application, it can be easy to exhaust this pool.

  11. There are 4 ways to do asynchronous delgates

    3 of these ways are similar. They are: block (by calling .EndInvoke() on the IAsyncResult object you get back from .BeginInvoke()), wait (by calling .WaitOne() on the IAsyncResult object), poll (by calling .WaitOne(timeout). All of these methods involve blocking or polling and require saving the IAsyncResult object.

    The 4th (and preferred) way involves providing a callback to the .BeginInvoke() call (this callback is a delgate that looks like public void Name(IAsyncResult result). In this case you do not need to says the IAsyncResult object because you get it in the callback.

  12. Make sure Aysnc callback methods catch exceptions

    If you do not catch exceptions in these callback methods, the thread pool will silently absorb (and ignore) them

  13. The [OneWay] attribute is a cheap way to mark any method as async

    Note that methods marked this way should return void, since they cannot return any values (the compiler does NOT enforce this). A natural place to put this is around the method in a source that notifies delgates - that will now happen asynchronously.