2013-08-21 2 views
0

У меня есть winform приложения, которое потребляет окно обслуживания, я пользователь ChannelFactory подключиться к службе, проблема, когда я называю метод обслуживания с использованием канал увеличения использования памяти и после метода выполнения памяти не идет вниз (даже после закрытия формы), я называю GC.Collect, но никаких измененийChannelFactory вызова метода increse память

канал Создать класс

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: База

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

Просто потому, что вы распоряжаетесь чем-то, это не означает, что он автоматически будет собран в GC следующей коллекции. Почему вы чувствуете, что вам нужно вручную вызвать GC, а не просто позволить программе управлять собой? Я настоятельно рекомендую вам прочитать [эту статью] (http://msdn.microsoft.com/en-us/magazine/bb985010.aspx), чтобы помочь вам понять, как работает сборщик мусора. –

+0

На самом деле у вас все еще есть живые ссылки на ваши каналы! Вы никогда не выпускаете ссылку, которая хранится как элемент в «Channel1».chanelList' –

+0

@ScottChamberlain Как я могу освободить ссылки на канал – test

ответ

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

Код выше получает новый ISales канал с завода в КАНАЛЕ, выполняет вызов, а затем закрывает канал. Если происходит исключение, канал прерывается в блоке catch.

Я бы не использовал Dispose() из коробки на каналах, так как реализация в структуре ошибочна и будет вызывать ошибку, если канал находится в неисправном состоянии. Если вы действительно хотите использовать Dispose() и принудительно собрать мусорную корзину, вы можете - но вам придется обойти проблему размещения WCF. Google предоставит вам ряд обходных путей (google WCF Using для начала).

Смежные вопросы