Sincronização de Threads em C# e VB.NET

1 Comentário

Aviso: Boa parte do conteúdo deste artigo é uma tradução de artigo “Thread Synchronization (C# and Visual Basic)” disponibilizado pela Microsoft, que pode ser encontrado aqui.

Um dos benefícios do uso de múltiplas threads em uma aplicação é que cada uma delas é executado de forma assíncrona. Em aplicações desktop, isto permite que tarefas que consomem muito tempo possam ser executadas em segundo plano enquanto a janela do aplicativo e os controles continuam respondendo. Para aplicações em servidores, múltiplas tarefas fornecem a capacidade de lidar com cada solicitação de entrada com uma thread diferente, caso contrário, cada novo pedido não será atendido até que o pedido anterior tenha completado.

No entanto, a natureza assíncrona de threads significa que o acesso a recursos compartilhados, como arquivos, conexões de rede e memória devem ser sincronizados. Caso contrário, duas ou mais threads podem acessar o mesmo recurso ao mesmo tempo, e cada um desconhece a atuação da outra ação e o resultado é a corrupção de dados imprevisível e possíveis deadlocks.

Há algum tempo, fiz outros artigos que demonstram o uso de threads em C# e Visual Basic. Você pode encontrá-los aqui:

Lock e SyncLock

O Lock (C#) e o SyncLock (VB.NET) são declarações que podem ser utilizadas para garantir que um bloco de código seja executado até sua conclusão, prevenindo a interrupção da execução por outras threads. Essas declarações são interpretadas pelo compilador como bloqueios para um determinado objeto em um bloco de códigos. Se outra thread tenta executar o código envolvido pelo lock / SyncLock, ela esperará até que a primeira thread termine a execução e libere o objeto / código bloqueado.

//C#
public class LockTest
{
    public void TestarLock()
    {
        lock (this)
        {
            // Código que estará protegido pelo lock.
        }
    }
}
'VB.NET
Public Class LockTest
    Public Sub TestarLock()
        SyncLock Me
            ' Código que estará protegido pelo lock.
        End SyncLock
    End Sub
End Class

Sincronização de Eventos e Wait Handles

Existem dois tipos de sincronização: AutoResetEvent e ManualResetEvent. Eles diferem apenas na medida em que as mudanças são setadas automaticamento no AutoResetEvent e manualmente no ManualResetEvent. O ManualResetEvent permite que qualquer número de threads possa ser alinhado e ter seu estado atualizado.

Métodos são usados para esperar a execução de um ou mais threads. Esses métodos indicam ao compilador quando e quantas threads devem ter o processamento concluído para que o fluxo continue. São eles: WaitOne, WaitAny e WaitAll. WaitOne faz com que o compilador espere a execução de um único thread estar concluída. WaitAny faz o compilador aguardar a execução dos métodos indicados. WaitAll bloqueia a execução até que todas as threads estejam concluídas. Para sinalizar a conclusão da execução de uma thread usa-se o método Set.

// C#
namespace GerenciaSincronizacao
{
    public class GerenciarThreads
    {
        private ManualResetEvent[] manualResetEvent;

        private void ExecutarThread0(object obj)
        {
            Thread.Sleep(20000);
            Console.WriteLine("Thread 0 concluída!");
            manualResetEvent[0].Set();
        }

        private void ExecutarThread1(object obj)
        {
            Thread.Sleep(13000);
            Console.WriteLine("Thread 1 concluída!");
            manualResetEvent[1].Set();
        }

        private void ExecutarThread2(object obj)
        {
            Thread.Sleep(9000);
            Console.WriteLine("Thread 2 concluída!");
            manualResetEvent[2].Set();
        }

        private void ExecutarThread3(object obj)
        {
            Thread.Sleep(17000);
            Console.WriteLine("Thread 3 concluída!");
            manualResetEvent[3].Set();
        }

        public void Executar()
        {
            manualResetEvent = new ManualResetEvent[4];

            manualResetEvent[0] = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(this.ExecutarThread0);

            manualResetEvent[1] = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(this.ExecutarThread1);

            manualResetEvent[2] = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(this.ExecutarThread2);

            manualResetEvent[3] = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(this.ExecutarThread3);

            WaitHandle.WaitAll(manualResetEvent);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            GerenciarThreads gt = new GerenciarThreads();
            gt.Executar();

            Console.WriteLine("Pressione ENTER para terminar.");
            Console.ReadKey();
        }
    }
}
' VB.NET
Namespace GerenciaSincronizacao
    Public Class GerenciarThreads
        Private manualResetEvent As ManualResetEvent()

        Private Sub ExecutarThread0(obj As Object)
            Thread.Sleep(20000)
            Console.WriteLine("Thread 0 concluída!")
            manualResetEvent(0).[Set]()
        End Sub

        Private Sub ExecutarThread1(obj As Object)
            Thread.Sleep(13000)
            Console.WriteLine("Thread 1 concluída!")
            manualResetEvent(1).[Set]()
        End Sub

        Private Sub ExecutarThread2(obj As Object)
            Thread.Sleep(9000)
            Console.WriteLine("Thread 2 concluída!")
            manualResetEvent(2).[Set]()
        End Sub

        Private Sub ExecutarThread3(obj As Object)
            Thread.Sleep(17000)
            Console.WriteLine("Thread 3 concluída!")
            manualResetEvent(3).[Set]()
        End Sub

        Public Sub Executar()
            manualResetEvent = New ManualResetEvent(3) {}

            manualResetEvent(0) = New ManualResetEvent(False)
            ThreadPool.QueueUserWorkItem(AddressOf Me.ExecutarThread0)

            manualResetEvent(1) = New ManualResetEvent(False)
            ThreadPool.QueueUserWorkItem(AddressOf Me.ExecutarThread1)

            manualResetEvent(2) = New ManualResetEvent(False)
            ThreadPool.QueueUserWorkItem(AddressOf Me.ExecutarThread2)

            manualResetEvent(3) = New ManualResetEvent(False)
            ThreadPool.QueueUserWorkItem(AddressOf Me.ExecutarThread3)

            WaitHandle.WaitAll(manualResetEvent)
        End Sub
    End Class

    Class Program
        Private Shared Sub Main(args As String())
            Dim gt As New GerenciarThreads()
            gt.Executar()

            Console.WriteLine("Pressione ENTER para terminar.")
            Console.ReadKey()
        End Sub
    End Class
End Namespace

A classe Interlocked

Você pode usar os métodos da classe Interlocked para evitar problemas que podem ocorrer quando várias threads tentam simultaneamente atualizar ou comparar um mesmo valor. Os métodos dessa classe permitem que você assegure o incremento, decremento, troca e comparação entre valores em qualquer thread.

As operações mais utilizadas desta classe são:

  • O método Add adiciona um valor inteiro para uma variável e retorna o novo valor da variável.
  • O método Read lê um valor inteiro de 64 bits.
  • Os métodos Increment e Decrement são utilizados para incrementar ou decrementar valores em uma variável e retornam o valor resultante.

O código a seguir demonstra o uso do Increment.

// C#
private static ManualResetEvent[] manualResetEvents;

public void Teste()
{
    int intQuantidadeInteracoes = 10;
    int intContador = 0;

    manualResetEvents = new ManualResetEvent[intQuantidadeInteracoes];

    for (int i = 0; i < intQuantidadeInteracoes; i++)
    {
        manualResetEvents[intContador] = new ManualResetEvent(false);

        ThreadPool.QueueUserWorkItem(this.Executar, intContador);

        Interlocked.Increment(ref intContador);
    }

    WaitHandle.WaitAll(manualResetEvents);
}

public void Executar(object intContador)
{
    Console.WriteLine("Posição atual do contador: {0}",
        Convert.ToInt32(intContador));

    manualResetEvents[Convert.ToInt32(intContador)].Set();
}
' VB.NET
Private Shared manualResetEvents As ManualResetEvent()

Public Sub Teste()
    Dim intQuantidadeInteracoes As Integer = 10
    Dim intContador As Integer = 0

    manualResetEvents = New ManualResetEvent(intQuantidadeInteracoes - 1) {}

    For i As Integer = 0 To intQuantidadeInteracoes - 1
        manualResetEvents(intContador) = New ManualResetEvent(False)

        ThreadPool.QueueUserWorkItem(AddressOf Me.Executar, intContador)

        Interlocked.Increment(intContador)
    Next

    WaitHandle.WaitAll(manualResetEvents)
End Sub

Public Sub Executar(intContador As Object)
    Console.WriteLine("Posição atual do contador: {0}", Convert.ToInt32(intContador))

    manualResetEvents(Convert.ToInt32(intContador)).[Set]()
End Sub

Referências

Anúncios

Extension Methods no C#

5 comentários

Apesar de ser um assunto de certa forma “esgotado”, que muitos estão cansados de saber, resolvi escrever este post, pois acho uma opção interessante para os desenvolvedores da plataforma .net.

Os métodos de extensão surgiram junto com o .Net Framework 3.5, e permitem adicionarmos novas funcionalidades a tipos existentes, sem a necessidade de alterar o tipo original e recompilá-lo. Devem sempre ser métodos estáticos, mas a chamada para eles é muito parecida com a chamada para métodos de instância. O primeiro parâmetro especifica em qual o tipo que método opera e deve sempre ser seguido da palavra chave this.

A classe que conterá o método de extensão, assim como o próprio método, também deve ser estática e a Namespace deve ser declarada nos locais onde o método de extensão deverá ficar disponível, através de using.

OBS: Todos os códigos contidos neste artigo estão em Linguagem C#

Vejamos um exemplo de criação método de extensão:

// C#
public static class MetodosDeExtensao
{
    /// <summary>
    /// Verifica se um objeto é nulo
    /// </summary>
    /// <param name="obj">object, objeto a ser verificado</param>
    /// <returns>bool, true quando o objeto for nulo</returns>
    public static bool IsNull(this object obj)
    {
        if (obj == null)
            return true;
        else
            return false;
    }
}

No exemplo acima, fizemos um método de extensão que verifica se um objeto é nulo ou não. É possível ver a palavra chave this antes a declaração do primeiro parâmetro do método, que é o identificador do tipo onde o método de extensão será aplicado.

O método em sí, terá a mesma estrutura de qualquer outro método estático, ou seja, não muda nada na forma de desenvolvimento e poderá ser usado normalmente como um método estático. Veja:

// C#
// utilizando a maneira convencional
string strNome = "Fernando Ottoboni";
if (MetodosDeExtensao.IsNull(strNome))
    Console.WriteLine("Nome não informado.");

Mas já que estamos falando de métodos de extensão, vamos então ver a forma correta de utilização do mesmo.

A partir do momento que o método de extensão foi criado, em todos os locais onde a namespace estiver acessível (lembre-se do using), o tipo declarado no método passará a conter uma nova extensão. Veja:

A seguir é possível ver um exemplo da sintaxe completa de utilização do nosso método de extensão.

// C#
// utilizando o método de extensão
string strNome = "Fernando Ottoboni";
if (strNome.IsNull())
    Console.WriteLine("Nome não informado.");

Em algumas situações, precisamos fazer métodos que devem ter dois ou mais parâmetros de entrada. Isso também é possível em métodos de extensão, mas devemos lembrar que sempre precisamos colocar o this no primeiro parâmetro (sempre no primeiro e somente nele). Os parâmetros restantes serão parâmetros comuns. Vejamos um exemplo:

// C#
/// <summary>
/// Completa a string com a quantidade e o caracter informado
/// </summary>
/// <param name="str">String, string a ser completada</param>
/// <param name="caracter">String, caracter a ser usado ao completar</param>
/// <param name="qt">Int, quantidade de caracteres</param>
/// <returns>String, string completada com os caracters</returns>
public static string CompletarString(this string str, string caracter, int qt)
{
    if (string.IsNullOrEmpty(str))
        str = "";

    if (caracter.Length > 1)
        caracter = caracter.Substring(0, 1);

    StringBuilder stb = new StringBuilder();

    if (string.IsNullOrEmpty(caracter.ToString()))
        caracter = " ";

    if (qt - str.Length > 0)
    {
        qt = qt - str.Length;
        stb.Append(str);
        stb.Append(new String(Convert.ToChar(caracter), qt));
    }
    else
    {
        stb.Append(str.Substring(0, qt));
    }

    return stb.ToString();
}

Existem várias outras situações e cenários onde podemos usar métodos de extensão. Vejamos então alguns lugares interessantes:

  • IsNullOrEmpty

Adquiri tão rapidamente o costume de usar métodos de extensão, que tive que fazer tornar o IsNullOrEmpty (String.IsNullOrEmpty) um deles apenas por conveniência.

// C#
/// <summary>Verficar se uma string é nula ou vazia</summary>
public static bool IsNullOrEmpty(this string str)
{
    return string.IsNullOrEmpty(str);
}
  • IsNullOrWhiteSpace

Assim como os IsNullOrEmpty, o mesmo pode ser feito com o IsNullOrWhiteSpace (String.IsNullOrWhiteSpace).

// C#
/// <summary>
/// Verficar se uma string é nula ou espaço em branco
/// </summary>
public static bool IsNullOrWhiteSpace(this string str)
{
    return string.IsNullOrWhiteSpace(str);
}
  • IsDateTime

Verificar se um string é um DateTime válido.

// C#
/// <summary>
/// Verificar se o conteúdo da string equivale a um DateTime
/// </summary>
public static bool IsDateTime(this string str)
{
    string strData = str;

    if (string.IsNullOrEmpty(strData))
        return false;

    try
    {
        DateTime datData = Convert.ToDateTime(strData);
        return true;
    }
    catch
    {
        return false;
    }
}
  • IsDecimal

Verificar se um string é um Decimal válido.

// C#
/// <summary>
/// Verificar se o conteúdo da string equivale a um decimal.
/// </summary>
public static bool IsDecimal(this string str)
{
    if (String.IsNullOrEmpty(str))
        return false;

    try
    {
        Convert.ToDecimal(str);
        return true;
    }
    catch
    {
        return false;
    }
}
  • ReverseString

Retorna a string reversa.

// C#
/// <summary>
/// Retorna a string de forma reversa
/// </summary>
/// <param name="str">String a ser revertida</param>
/// <returns>String revertida</returns>
public static string ReverseString(this string str)
{
    char[] arr = str.ToCharArray();
    Array.Reverse(arr);
    return new string(arr);
}
  • Left

Extrai um Substring do lado esquerdo da string conforme a quantidade de caracteres desejada.

// C#
/// <summary>
/// Extrai um Substring do lado esquerdo da string
/// conforme a quantidade de caracteres desejada
/// </summary>
/// <param name="str">String para extrair o substring</param>
/// <param name="length">Quantidade de caracteres a extrair</param>
/// <returns>String</returns>
public static string Left(this string str, int length)
{
    if (str.IsNullOrEmpty())
        return str;

    if (str.Length <= length)
        return str;

    return str.Substring(0, length);
}
  • Right

Extrai um Substring do lado direito da string conforme a quantidade de caracteres desejada.

OBS: Usa o método ReverseString.

// C#
/// <summary>
/// Extrai um Substring do lado direito da string conforme a quantidade de caracteres desejada
/// </summary>
/// <param name="str">String para extrair o substring</param>
/// <param name="length">Quantidade de caracteres a extrair</param>
/// <returns>String</returns>
public static string Right(this string str, int length)
{
    if (str.IsNullOrEmpty())
        return str;

    if (str.Length <= length)
        return str;

    return str.ReverseString().Substring(0, length).ReverseString();
}

Existem muitas outras possibilidades, e no código fonte que pode ser baixado logo abaixo coloquei alguns outros exemplos.

LINQ e os Métodos de Extensão

Há algum tempo, fiz um artigo que mostrei como utilizar e como funcionam os métodos de extensão disponíveis para utilização com LINQ. Se quiser conferir, basta clicar aqui.

Códigos fontes

Os códigos-fontes deste artigo podem ser baixados aqui.

Referências

Novo artigo no iMasters

Deixe um comentário

Mais um artigo publicado no iMasters:

Recebendo retornos de threads em C#

Existem situações em que é necessário retornar informações quando a execução da thread estiver concluída para que elas sejam usadas na continuação do processamento da thread principal da aplicação. O intuito deste artigo é mostrar uma maneira de receber e tratar retornos de threads.

Neste link: imasters.com.br/artigo/19615/c-sharp/recebendo-retornos-de-threads-em-c

Vale a pena conferir!

Obrigado.

Artigo no iMasters

Deixe um comentário

Tive meu primeiro artigo publicado no iMasters. Apesar de ser um artigo que já havia publicado aqui no blog, vale a pena conferir pois fiz pequenas modificações para melhorar o conteúdo.

Programando threads em C#

Usar threads é sempre vantajoso no ponto de vista de que podemos aproveitar o poder de processamento dos processadores que possuem mais de um núcleo, pois podemos programar para que cada thread tenha o seu processamento realizado por núcleos diferentes.

Neste link: http://imasters.com.br/artigo/19541/csharp/programando_threads_em_c/

Obrigado.

Visual Studio LightSwitch

Deixe um comentário

A Microsoft liberou para a comunidade do MSDN em 18/09 o download do Visual Studio LightSwitch na versão beta, que promete permitir que usuários não desenvolvedores criem aplicações windows, web e nas nuvens. Além disso, é possível utilizar VB.Net e C# nas aplicações.

O Visual Studio LightSwitch utiliza modelos e outros componentes que facilitam a criação de aplicações para PCs, para a Web e para a nuvem e, em muitos casos, não requer que o usuário tenha que lidar com o código durante o processo.

De acordo com a Microsoft, os usuários do LightSwitch podem usar o Visual Basic ou C# para as aplicações e podem até mesmo conectar suas aplicações ao Excel, SharePoint ou aos serviços do Windows Azure.

Além disso, os usuários podem criar suas aplicações para que elas sejam executadas em qualquer ambiente compatível com o Silverlight: navegadores (Internet Explorer, Safari, Firefox), em PCs com o Windows ou no Windows Azure, por exemplo.

Embora o Visual Studio LightSwitch Beta 1 esteja disponível hoje para os assinantes da MSDN, ele será disponibilizado para download público apenas na próxima segunda-feira, 23 de agosto, através do LightSwitch Developer Center.

Fonte: Baboo

Saiba mais:

Trabalhando com tipos anuláveis

Deixe um comentário

Existem algumas situações onde precisamos estabelecer que uma variável pode ser nula. Isso acontece com muita frequência quando utilizando Modelos Objeto-Relacional, onde uma “cópia” da estrutura das tabelas da base de dados é feita dentro do modelo gerado no Visual Studio em forma de classes. Declarar variáveis como anuláveis é extremamente simples, e pode ser feito assim:

// C# - Pode ser assim
System.Nullable<decimal> decimalAnulavel = null;
System.Nullable<int> inteiroAnulavel = null;
System.Nullable<bool> booleanAnulavel = null;
// C# - Ou assim
decimal? decimalAnulavel = null;
int? inteiroAnulavel = null;
bool? booleanAnulavel = null;
' VB.NET - Existe uma única maneira
Dim decimalAnulavel As Nullable(Of Decimal) = Nothing
Dim inteiroAnulavel As Nullable(Of Integer) = Nothing
Dim booleanAnulavel As Nullable(Of Boolean) = Nothing

Como exemplo, uma variável bool anulável pode receber True, False e Null.

Ao declarar uma variável como anulável, são habilitadas duas novas propriedades:
  • HasValue: determina se a variável anulável possue valor.
  • Value: contém o valor não nulo da variável

Essas duas propriedades pode ser usadas em conjunto, como o código a seguir demonstra.

// C#
if (decimalAnulavel.HasValue)
    Console.WriteLine(decimalAnulavel.Value.ToString());
else
    Console.WriteLine("Valor nulo");
' VB.NET
If (decimalAnulavel.HasValue) Then
    Console.WriteLine(decimalAnulavel.Value.ToString)
Else
    Console.WriteLine("Valor Nulo")
End If

O Operador ?? do C#

O operador ?? facilita a manipulação de tipos anuláveis. Com ele podemos informar um valor fixo caso a variável seja nula.

// C#
Console.WriteLine((decimalAnulavel ?? decimal.Zero).ToString());

No VB.NET é bem parecido, mas não existe o operador ??, então usa-se o próprio If.

' VB.NET
Console.WriteLine((If(decimalAnulavel, Decimal.Zero)).ToString())

O Operador ?: do C#

O operador ?: funciona como um If, com a sintaxe (condicao ? true : false).

// C#
Console.WriteLine((decimalAnulavel.HasValue ?
                   decimalAnulavel.Value.ToString() :
                   "Valor nulo"));

No VB.NET é bem parecido, mas não existe o operador ?:, então usa-se o próprio If.

' VB.NET
Console.WriteLine((If(decimalAnulavel.HasValue, _
                      decimalAnulavel.Value.ToString(), _
                      "Valor nulo")))

Saiba mais:

Obrigado.

Exemplo de Implementação de IDisposable

3 comentários

A interface IDisposable é usada para liberar recursos. O garbage collector (coletor de lixo) libera automaticamente a memória alocada para um objeto gerenciado quando este objeto não estiver mais sendo utilizado. No entanto, não é possível prever quando esta coleta de lixo irá ocorrer. Além disso, o garbage collector não tem conhecimento dos recursos não gerenciados.

Usamos o método Dispose desta interface para liberar explicitamente recursos não gerenciados em conjunto com o garbage collector. O consumidor de um objeto pode chamar esse método quando o objeto não for mais necessário.

Inicialmente, precisamos fazer a classe que queremos implementar IDisposable herdar desta interface.

// C#
public class GerenciarClientes : IDisposable
{
    public void Dispose()
    {

    }
}

 

' VB.NET
Public Class GerenciarClientes
    Implements IDisposable

    Public Overridable Sub Dispose() Implements IDisposable.Dispose

    End Sub
End Class

OBS: Em C#, para que o próprio Visual Studio implemente o método Dispose, basta clicar com o botão direito do mouse sobre a interface, escolher a opção ‘Implement Interface’ e ‘Implement Interface’ novamente. Esse mesmo procedimento funciona com a implementação de qualquer interface em uma classe.

Para controlarmos corretamente a liberação dos recursos, é necessário criar uma variável do tipo booleana, que indicará se o método Dispose já foi disparado.

Além disso, precisamos criar um método privado que será chamado de lugares distintos e controlará quais recursos (gerenciados ou não) devem ser liberados.

// C#

// booleano para controlar se
// o método Dispose já foi chamado
bool disposed = false;

// método privado para controle
// da liberação dos recursos
private void Dispose(bool disposing)
{
    // Verifique se Dispose já foi chamado.
    if (!this.disposed)
    {
        if (disposing)
        {
            // Liberando recursos gerenciados

        }

        // Seta a variável booleana para true,
        // indicando que os recursos já foram liberados
        disposed = true;
    }
}

 

' VB.NET

' booleano para controlar se
' o método Dispose já foi chamado
Private disposed As Boolean = False

' método privado para controle
' da liberação dos recursos
Private Sub Dispose(ByVal disposing As Boolean)
    ' Verifique se Dispose já foi chamado.
    If Not Me.disposed Then
        If disposing Then
            ' Liberando recursos gerenciados

        End If

        ' Seta a variável booleana para true,
        ' indicando que os recursos já foram liberados
        disposed = True
    End If
End Sub

Dentro do método público Dispose, é necessário chamar o método privado Dispose e também informar o garbage collector para não chamar o método finalizador da classe, pois estamos controlando isso manualmente. Para isto, utilizamos o método GC.SuppressFinalize().

// C#
bool disposed = false;

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

 

' VB.NET
Dim disposed As Boolean = False

Protected Overridable Sub Dispose() Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub

Por fim, precisamos programar o método finalizador da classe, que é invocado pelo garbage collector para liberar os recursos. Toda liberacao implementada dentro dele só será executada quando o metodo for invocado, porém não conseguimos saber quando isto vai acontecer e recursos importantes podem ficar presos até que isto aconteça.

// C#
~GerenciarClientes()
{
    Dispose(false);
}
' VB.NET
Protected Overrides Sub Finalize()
    Dispose(False)
    MyBase.Finalize()
End Sub

Pronto, implementamos IDisposable. Com essa implementação, sempre que tivermos uma instância da classe que não será mais utilizada, devemos chamar o método Dispose ou envolvê-la em um bloco using.

// C#

// forma simples
GerenciarClientes g1 = new GerenciarClientes();

// código consumidor da instância

// Liberando o recurso
g1.Dispose();

// usando try...finally
GerenciarClientes g2 = new GerenciarClientes();
try
{
    // código consumidor da instância
}
finally
{
    g2.Dispose();
}

// ou com using
using (GerenciarClientes g3 = new GerenciarClientes())
{
    // código consumidor da instância
} // aqui o método Dispose é invocado

 

' VB.NET

' forma simples
Dim g1 As New GerenciarClientes()
' código consumidor da instância

' Liberando o recurso
g1.Dispose()

' usando Try...Finally
Dim g2 As New GerenciarClientes()
Try
    ' código consumidor da instância
Finally
    g2.Dispose()
End Try

' ou com using
Using g3 As New GerenciarClientes()
    ' código consumidor da instância
End Using ' aqui o método Dispose é invocado


Referências

Código Fonte

O código fonte deste post pode ser baixado aqui.



Obrigado

Older Entries