Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

amiloM1425

Semáforos

Recommended Posts

amiloM1425

Olá a todos,

é a primeira vez que estou a trabalhar com semáforos em C#, e também para ser sincero nunca semáforos nunca foi o meu forte.

A questão é a seguinte, tenho uma classe estática que vai guardando informação durante o decorrer da aplicação. A essa classe poderão aceder várias threads, e claro existem zonas criticas. Basicamente estou a fazer um sem.WaitOne() quando vou ler/escrever nas zonas criticas e depois faço o sem.Release(). O problema é que a uma determinada altura fica tudo bloqueado, parece uma situação de Deadlock, fica tudo à espera que haja um release.

Aqui fica a classe, se pudessem dar uma vista de olhos e comentar o que está mal agradecia, pois como já referi há pouco não tenho muita experiência com semáforos.

    class DadosActuais
    {
        static Semaphore sem = new Semaphore(1, 1);

        static ArrayList numeroSerieDesconhecidos = new ArrayList();
        static ArrayList numeroSerieConhecidos = new ArrayList();

        /// <summary>
        /// Adiciona um novo nº de série à lista de nº de série conhecidos
        /// </summary>
        /// <param name="numeroSerie">Nº de série a adicionar</param>
        public static void addNumeroSerieConhecido(string numeroSerie)
        {
            sem.WaitOne();

            numeroSerieConhecidos.Add(numeroSerie);
            
            sem.Release();
        }

        /// <summary>
        /// Adiciona um novo nº de série à lista de nº de série desconhecidos
        /// </summary>
        /// <param name="numeroSerie"></param>
        public static void addNumeroSerieDesconhecido(string numeroSerie)
        {
            sem.WaitOne();

            foreach (string nSerie in numeroSerieDesconhecidos)
            {
                if (nSerie.CompareTo(numeroSerie) == 0)
                    return;
            }
            numeroSerieDesconhecidos.Add(numeroSerie);

            sem.Release();
        }

        /// <summary>
        /// Limpa a lista de nº de série desconhecidos
        /// </summary>
        public static void limpaNumeroSerieDesconhecido()
        {
            sem.WaitOne();

            numeroSerieDesconhecidos.Clear();

            sem.Release();
        }

        /// <summary>
        /// Obtém o indice da posição em que se encontra guardado o nº de série do equipamento
        /// </summary>
        /// <param name="numeroSerie">Nº de série do equipamento</param>
        /// <returns>Devolve o indice em que se encontra guardade o equipamento</returns>
        private static int getIndiceEquipamento(string numeroSerie)
        {
            int i = 0;
            foreach (string nSerie in numeroSerieConhecidos)
            {
                if (nSerie.CompareTo(numeroSerie) == 0)
                    return i;
                i++;
            }
            return i;
        }

        /// <summary>
        /// Guarda os nº de série registados na base de dados
        /// </summary>
        /// <param name="lista">Lista com equipamentos registados na base de dados</param>
        public static void carregaDados(ArrayList listaEq)
        {
            foreach (Equipamento eq in listaEq)
            {
                addNumeroSerieConhecido(eq.numeroSerie);
            }
        }

        /// <summary>
        /// Verifica se o nº de série é de um equipamento conhecido
        /// </summary>
        /// <param name="numeroSerie">Nº de série</param>
        /// <returns>Devolve true caso o nº de série pertença a um equipamento conhecido ou false caso contrário</returns>
        public static bool verificaExisteConhecido(string numeroSerie)
        {
            sem.WaitOne();
            foreach (string nSerie in numeroSerieConhecidos)
            {
                if (nSerie.CompareTo(numeroSerie) == 0)
                {
                    sem.Release();
                    return true;
                }
            }
            sem.Release();
            return false;
        }

        /// <summary>
        /// Verifica se o nº de série é de um equipamento desconhecido
        /// </summary>
        /// <param name="numeroSerie">Nº de série</param>
        /// <returns>Devolve true caso o nº de série pertença a um equipamento desconhecido ou false caso contrário</returns>
        public static bool verificaExisteDesconhecido(string numeroSerie)
        {
            sem.WaitOne();
            foreach (string nSerie in numeroSerieDesconhecidos)
            {
                if (nSerie.CompareTo(numeroSerie) == 0)
                {
                    sem.Release();
                    return true;
                }
            }
            sem.Release();
            return false;
        }
}

Share this post


Link to post
Share on other sites
Betovsky

Na função addNumeroSerieDesconhecido se o if for verdadeiro não estás a libertar o semáforo.


"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Share this post


Link to post
Share on other sites
amiloM1425

Obrigado pela ajuda. Realmente quando se está demasiado tempo a olhar para o mesmo código já se começa a não ver nada à frente :D

Share this post


Link to post
Share on other sites
Njay

O C# não tem um "try .. catch"? Se não tem, podes fazer como eu faço em linguagens que não o têm, por exemplo C:

sem.get
do {
    ....
    if error { error = ... ; break; }
    ...
    if error { error = ... ; break; }
    ...
} while (0);
sem.release

Tás a ver a ideia? Há várias variações conforme a aplicação. E ainda podes "embrulhar" várias partes em macros bonitinhas, nas linguagens que as suportem. Só tens que ter cuidado para não aninhar vários niveis, isto só suporta 1.


Blog: Tróniquices ~ Projecto: EmbeddedDreams.com

Share this post


Link to post
Share on other sites
amiloM1425

Sim, o C# tem Try{ } Catch{ }. Ainda vou ter de fazer o tratamento de excepções. De qualquer forma obrigado pela sugestão.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.