Question

I am a bit of a n00b with memory allocation, but I am trying to understand how using AsyncCallbacks with the BeginInvoke type design pattern might cause a memory allocation and thusly might cause the garbage collector to be invoked more frequently.

For instance, if I had a class with an event that I wished to invoke asynchronously with a callback, I would normally set it up as follows:

Method I

public class PriceBook
{
    private double Value;

    public void UpdateValue(double Value)
    {
        this.Value = Value;
    }

    public event EventHandler ValueUpdated;
    private void DoValueUpdated(double Value)
    {
        if (ValueUpdated != null)
        {
            ValueUpdated.BeginInvoke(this, EventArgs.Empty, ValueUpdateCompleted, Value);
        }
    }

    private void ValueUpdateCompleted(IAsyncResult ar)
    {
        // Do something when event has finished being called.
    }
}

Somebody that I work with says that calling the BeginInvoke in this way actually allocates memory by creating a new AsyncCallback every time it is called. So, he suggested doing it like this instead:

Method II

public class PriceBook
{
    private AsyncCallback ValueUpdateCallback;
    private double Value;

    public PriceBook1()
    {
        ValueUpdateCallback = ValueUpdateCompleted;
    }

    public void UpdateValue(double Value)
    {
        this.Value = Value;
        DoValueUpdated(Value);
    }

    public event EventHandler ValueUpdated;
    private void DoValueUpdated(double Value)
    {
        if (ValueUpdated != null)
        {
            ValueUpdated.BeginInvoke(this, EventArgs.Empty, ValueUpdateCallback, Value);
        }
    }

    private void ValueUpdateCompleted(IAsyncResult ar)
    {
        // Do something when event has finished being called.
    }
}

As you can see, here I set the AsyncCallback once in the constructor. Does method II really save on memory allocation? Are there any other benefits of either method/is there an even better way of accomplishing what I am trying to do?

  • William
Was it helpful?

Solution

Yes, that saves one delegate allocation.

This

ValueUpdated.BeginInvoke(..., ValueUpdateCompleted, ...);

is really this:

ValueUpdated.BeginInvoke(..., new AsyncCallback(ValueUpdateCompleted), ...);

You can see the allocation now.

If the invocation is not on a hot path, meaning that it is not performance critical, I recommend not to cache the delegate because code maintainability is suffering from it.

Also, a thread-pool invocation is a lot more expensive than that delegate allocation. I cannot imagine a situation where this might make a difference.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top