【问题标题】:Actions/AsyncCallbacks and Memory Allocation操作/异步回调和内存分配
【发布时间】:2012-08-20 20:19:37
【问题描述】:

我对内存分配有点不了解,但我想了解如何将 AsyncCallbacks 与 BeginInvoke 类型设计模式一起使用可能会导致内存分配,从而可能导致更频繁地调用垃圾收集器。

例如,如果我有一个带有事件的类,我希望通过回调异步调用它,我通常会按如下方式设置它:

方法一

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.
    }
}

与我一起工作的人说,以这种方式调用 BeginInvoke 实际上是通过在每次调用时创建一个新的 AsyncCallback 来分配内存。所以,他建议这样做:

方法二

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.
    }
}

如您所见,这里我在构造函数中设置了一次 AsyncCallback。方法二真的可以节省内存分配吗?这两种方法还有其他好处吗/是否有更好的方法来完成我想做的事情?

  • 威廉

【问题讨论】:

    标签: c# multithreading memory-management asynccallback


    【解决方案1】:

    是的,这样可以节省一个委托分配。

    这个

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

    真的是这样的:

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

    你现在可以看到分配了。

    如果调用不在热路径上,这意味着它不是性能关键,我建议不要缓存委托,因为它会影响代码的可维护性。

    此外,线程池调用比委托分配要昂贵得多。我无法想象这可能会产生影响的情况。

    【讨论】:

    • 上面的例子只是一个简单的例子来说明这个问题——在我的实际应用程序中,我们不调用 .NET 线程池——不过谢谢你的解释!
    猜你喜欢
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    相关资源
    最近更新 更多