我有一个使用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();
}
}
答案 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使用起初)。