Winforms ChannelFactory方法调用增加内存

Winforms ChannelFactory方法调用增加内存,winforms,wcf,channelfactory,Winforms,Wcf,Channelfactory,我有一个使用windows服务的winform应用程序,我的用户ChannelFactory 要连接到服务,问题是当我使用通道调用服务方法时,内存使用量会增加 方法执行内存不下降(即使在窗体关闭之后),我调用GC.Collect,但没有更改 通道创建类 public class Channel1 { List<ChannelFactory> chanelList = new List<ChannelFactory>(); ISales salesObj; public

我有一个使用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;
}
}
winform类
表格1:基础

 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();
            }
        }

就使用
ChannelFactory
而言,您已经走上了正确的道路,但是您的实现有点偏离了

ChannelFactory
创建用于生成T型通道的工厂。这是一个相对昂贵的操作(与仅从现有工厂创建通道相比),并且通常在应用程序的每个生命周期(通常在启动时)执行一次。然后,您可以使用该工厂实例创建应用程序所需的任意多个通道

通常,一旦我创建了工厂并缓存了它,当我需要调用服务时,我会从工厂获得一个通道,进行调用,然后关闭/中止该通道

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

public class Channel1
{

    ChannelFactory<ISales> salesChannel;

    public ISales Sales
    {
        get
        {
            if (salesChannel == null)
            {
                salesChannel = new ChannelFactory<ISales>("SalesEndPoint");
            }
            return salesChannel.CreateChannel();
        }
    }       
}
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);
    }
}
上面的代码从通道中的工厂获取一个新的ISales通道,执行调用,然后关闭通道。如果发生异常,则在catch块中中止通道


我会避免在通道上使用开箱即用的
Dispose()
,因为框架中的实现存在缺陷,如果通道处于故障状态,就会抛出错误。如果您真的想使用
Dispose()
并强制执行垃圾收集,您可以-但您必须解决WCF Dispose问题。Google将为您提供许多解决方法(Google WCF首先使用)。

仅仅因为您处理了一些东西,并不意味着它将自动被GC下一次收集收集。为什么您觉得需要手动调用GC,而不仅仅是让程序自行管理?我强烈建议您阅读以帮助您了解垃圾收集器的工作原理。事实上,您仍然有对频道的实时引用!您从未释放作为项目保存在
Channel1.chanelList
@ScottChamberlain中的引用我如何才能释放channelreferences@ScottChamberlainCHANNEL.CloseAllChannels()是否不释放引用为什么每次需要频道时都要创建频道工厂?只需创建一次ChannelFactory,然后在需要新频道时在factory上调用
CreateChannel()
。我建议创建频道,使用它,然后关闭它。一次(可能)拥有同一个ChannelFactory的多个副本是没有意义的。
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);
    }
}