Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #57 da revista programar. Faz já o download aqui!

amiloM1425

Semáforos

Mensagens Recomendadas

amiloM1425    0
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


Link para a mensagem
Partilhar noutros sites
Njay    0
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.

Partilhar esta mensagem


Link 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 a nossa Política de Privacidade