Ir para o conteúdo
amiloM1425

Semáforos

Mensagens Recomendadas

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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.