ChannelFactory方法调用增加内存

时间:2013-08-21 08:47:36

标签: winforms wcf channelfactory

我有一个使用Windows服务的winform应用程序,我是用户ChannelFactory 连接到服务,问题是当我使用通道调用服务方法时内存使用量增加和之后 方法执行内存不下降(即使在表单关闭后),我调用GC.Collect但没有更改

频道创建课程

public class Channel1
{
List<ChannelFactory> chanelList = new List<ChannelFactory>();
ISales salesObj;

public ISales Sales
{
    get
    {
        if (salesObj == null)
        {
            ChannelFactory<ISales> saleschannel = new ChannelFactory<ISales>("SalesEndPoint");
            chanelList.Add(saleschannel);
            salesObj = saleschannel.CreateChannel();
        }
        return salesObj;
    }
}

public void CloseAllChannels()
{
    foreach (ChannelFactory chFac in chanelList)
    {
        chFac.Abort();
        ((IDisposable)chFac).Dispose();            
    }
    salesObj = null;
}
}

基类

public class Base:Form
    {    
       public Channel1 channelService = new Channel1();        
       public Channel1 CHANNEL
       {
           get
           {
               return channelService;
           }
       }                  
    }

winform class
Form1中:基

 private void btnView_Click(object sender, EventArgs e)
        {
            DataTable _dt = new DataTable();
            try
            {
                gvAccounts.AutoGenerateColumns = false;
                _dt = CHANNEL.Sales.GetDatatable();
                gvAccounts.DataSource = _dt;

            }
            catch (Exception ex)
            {    
                MessageBox.Show("Error Occurred while processing...\n" + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            finally
            {
                CHANNEL.CloseAllChannels();
                _dt.Dispose();
                //GC.Collect();
            }
        }

1 个答案:

答案 0 :(得分:1)

您在使用ChannelFactory<T>方面处于正确的轨道,但您的实施有点偏。

ChannelFactory<T>创建了一个工厂,用于生成类型为T的通道。这是一个相对昂贵的操作(与仅从现有工厂创建通道相比),通常在应用程序的每个生命周期内完成一次(通常在开始)。然后,您可以使用该工厂实例创建与应用程序需求一样多的通道。

通常,一旦我创建工厂并缓存它,当我需要拨打服务时,我会从工厂获得一个频道,拨打电话,然后关闭/中止频道。

使用您发布的代码作为起点,我会这样做:

public class Channel1
{

    ChannelFactory<ISales> salesChannel;

    public ISales Sales
    {
        get
        {
            if (salesChannel == null)
            {
                salesChannel = new ChannelFactory<ISales>("SalesEndPoint");
            }
            return salesChannel.CreateChannel();
        }
    }       
}

请注意,我已将salesObj替换为salesChannel(工厂)。这将在第一次调用时创建工厂,并且每次都会从工厂创建一个新的通道。

除非您有特殊要求,否则我不会跟踪不同的渠道,特别是如果遵循open / do方法/关闭方法。

在您的表单中,它看起来像这样:

private void btnView_Click(object sender, EventArgs e)
{

    DataTable _dt = new DataTable();

    try
    {
        gvAccounts.AutoGenerateColumns = false;
        ISales client = CHANNEL.Sales
        _dt = client.GetDatatable();
        gvAccounts.DataSource = _dt;
        ((ICommunicationObject)client).Close();
    }
    catch (Exception ex)
    {    
        ((ICommunicationObject)client).Abort();
        MessageBox.Show("Error Occurred while processing...\n" + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }
}

上面的代码从CHANNEL的工厂获取一个新的ISales通道,执行调用,然后关闭通道。如果发生异常,则会在catch块中中止通道。

我会避免在频道上使用Dispose()开箱即用,因为框架中的实现存在缺陷,如果频道处于故障状态,则会抛出错误。如果你真的想使用Dispose()并强制垃圾收集,你可以 - 但你必须解决WCF处理问题。谷歌将为您提供一些解决方法(谷歌WCF使用起初)。