Pergunta

Tenho uma aplicação que tem dois threads.

O primeiro (o segmento principal) que captura os dados usando soquete e atualizar tabelas de dados

O segundo Insere os DataTables no banco de dados.

O aplicativo funciona bem, mas quando ele fecha, os principais acabamentos segmento de leitura de dados e chamadas Abort método no segundo segmento, que pode ser a inserção no banco de dados e isso leva a dados inconsistentes.

Atualmente estou usando a seguinte solução para superar "abortar durante a inserção"

EDIT: Após as respostas poderosas eu mudei o código

void MainThread()
{
     while(Read())
     {
        //Read Data through socket
        try
        {
           //Wait on Mutex1
           //Update Tables
        }
        finally
        {
          //Release Mutex1
        }
     }
   _isrunning = false;
   _secondThread.Join();
}
void SecondThread()
{
     while(_isrunning)
     {
        try
        {
           //Wait on Mutex1
           //Insert Tables into Database using transactions
        }
        finally
        {
           //Release Mutex1           
        }
     }
}
Foi útil?

Solução

Assumindo que "chamada de abort método" significa abortar o segmento usando Thread.Abort. Não faça isso .

Você está efetivamente bater seu aplicativo. Existem formas mais limpas abundância de fazer isso com monitores.

No entanto, você não deve estar recebendo dados inconsistentes na sua DB quando suas falhas de aplicativos é por isso que você tem transações de banco de dados que têm a propriedades ACID .

EDIT MUITO IMPORTANTE Você disse: você não usar transações por motivos de desempenho, e em vez disso usar mutexes. Esta é ERRO em muito poucos níveis. Em primeiro lugar, as transações podem fazer certas operações mais rápido, por exemplo, tente inserir 10 linhas em uma tabela, tente novamente dentro de uma transação, a versão transação será mais rápido. Em segundo lugar, o que acontece quando / se o seu aplicativo trava, você corromper o seu banco de dados? O que acontece quando várias instâncias do seu aplicativo está executando? Ou quando você executar relatórios contra o DB no Query Analyzer?

Outras dicas

Enquanto os dois segmentos não são marcados como threads em segundo plano, o aplicativo continuará a funcionar até que ambos saída threads. Então, realmente, tudo o que você precisa fazer é fazer com que cada segmento separadamente para sair de forma limpa. No caso do segmento que escreve para o banco de dados, isso pode significar esgotar um produtor / consumidor filas e verificar um sinalizador para sair.

Eu mostrei um produtor / consumidor adequado fila aqui - o trabalhador seria apenas:

void WriterLoop() {
    SomeWorkItem item; // could be a `DataTable` or similar
    while(queue.TryDequeue(out item)) {
        // process item
    }
    // queue is empty and has been closed; all done, so exit...
}

Aqui está um exemplo completo baseado em SizeQueue<> - nota que o processo não sair até que o leitor e escritor ter saído de forma limpa. Se você não quer ter de drenar a fila (ou seja, você quer sair mais cedo, e esquecer qualquer trabalho pendente), então tudo bem -. Adicionar um extra (volátil) flag em algum lugar

static class Program {
    static void Write(object message) {
        Console.WriteLine(Thread.CurrentThread.Name + ": " + message);
    }
    static void Main() {
        Thread.CurrentThread.Name = "Reader";
        Thread writer = new Thread(WriterLoop);
        writer.Name = "Writer";
        var queue = new SizeQueue<int>(100);
        writer.Start(queue);
        // reader loop - note this can run parallel
        // to the writer
        for (int i = 0; i < 100; i++) {
            if (i % 10 == 9) Write(i);
            queue.Enqueue(i);
            Thread.Sleep(5); // pretend it takes time
        }
        queue.Close();
        Write("exiting");
    }
    static void WriterLoop(object state) {
        var queue = (SizeQueue<int>)state;
        int i;
        while (queue.TryDequeue(out i)) {
            if(i%10==9) Write(i);
            Thread.Sleep(10); // pretend it takes time
        }
        Write("exiting");
    }
}

Sua espera mutex deve envolver um tempo limite. loop externo de cada segmento pode verificar a existência de uma bandeira 'Por favor, feche empresa'. Para desligar, defina o sinalizador 'por favor perto agora' para cada thread, então use 'juntar' esperar para cada thread ao fim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top