0

我有一个winform使用 Windows 服务的应用程序,我用户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 类
Form1:Base

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

1 回答 1

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

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

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

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

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 使用开始)。

于 2013-08-22T05:49:54.340 回答