É “errado” / mau design colocar um trabalhador de thread / background em uma classe?


15

Eu tenho uma classe que lerá do Excel (C # e .Net 4) e nessa classe eu tenho um trabalhador em segundo plano que carregará os dados do Excel enquanto a interface do usuário permanecer responsiva. Minha pergunta é a seguinte: É um design ruim ter um trabalhador em segundo plano em uma classe? Devo criar minha classe sem ela e usar um trabalhador em segundo plano para operar nessa classe? Não vejo realmente nenhum problema em criar minha turma dessa maneira, mas, novamente, sou novato, então pensei em me certificar antes de continuar.

Espero que essa questão seja relevante aqui, pois não acho que deva estar no stackoverflow, pois meu código funciona, isso é apenas uma questão de design.


3
por que você acha que pode estar errado?
Alb

1
@ Alb - é difícil dizer. Meu código funciona e preenche minhas necessidades, no entanto, estou planejando usá-lo em um projeto que tornarei open source. Quero garantir que meu código não "funcione" e que seja realmente bem projetado.
1128 Jetti

Respostas:


21

Devo criar minha classe sem ela e usar um trabalhador em segundo plano para operar nessa classe?

Sim você deveria. E eu lhe direi o porquê - você está violando o Princípio da Responsabilidade Única . Ao acoplar firmemente a classe que acessa o documento do Excel com a forma como ele acessa o documento do Excel, você elimina a capacidade do código do "controlador" (qualquer código que use isso) de fazê-lo de maneira diferente. Quão diferente, você pode perguntar? E se o código do controlador tiver duas operações que demoram muito tempo, mas quer que sejam sequenciais? Se você tiver permitido ao controlador lidar com o encadeamento, ele poderá executar as duas tarefas de longa duração juntas em um único encadeamento. E se você deseja acessar o documento do Excel a partir de um contexto que não seja da interface do usuário e não precisa ser encadeado?

Ao passar a responsabilidade de passar para o chamador, você permite maior flexibilidade do seu código, tornando-o mais reutilizável.


2
+1 para responder à pergunta real solicitada e responder bem.
Adam Lear

+1 - Obrigado Nemi. Você respondeu minha pergunta imediatamente, eu agradeço. Vou tirar isso da minha classe e colocá-lo em uma nova aula, obrigado novamente!
Jetti 04/04

@ Nemi - então seria aceitável se eu criasse outro método que teria uma carga síncrona e depois tivesse um método assíncrono? Ou seria melhor ter o método de carregamento síncrono e depois partir daí?
Jetti

1
Eu, pessoalmente, não teria um método de sincronização e um método assíncrono. Você ainda está acoplando responsabilidades. Eu trabalhei com esse problema exato muitas vezes. O que fiz foi criar um TaskController que foi modelado após o SwingWorker, mas tinha um código específico para o nosso aplicativo. O TaskController fez coisas como atualizar uma barra de progresso, alterar o cursor do mouse etc. Pode parecer um código da placa da caldeira sempre ter que criar um TaskController para fazer chamadas, mas, finalmente, o código é mais robusto e mais sustentável.
Nemi

Obrigado Nemi! Eu gostaria de poder te votar novamente, porque você definitivamente respondeu minha pergunta e me indicou a direção certa. Mais uma vez obrigado !!
Jetti

3

É bom design para que as operações da interface do usuário operem em um thread separado das tarefas em segundo plano. Caso contrário, a interface do usuário não responderá quando o aplicativo estiver ocupado.

Se você pode separar a parte que funciona no encadeamento em segundo plano em sua própria classe, o código será mais limpo.


1
Embora correto, de como li a pergunta dele, ele não tem problemas para entender esse ponto.
Nemi

Sinto muito se minha pergunta foi mal interpretada. Sei que separar a interface do usuário e as tarefas em segundo plano é um bom design (se não for necessário, meu arquivo do excel de teste tem mais de 8k linhas e faria o programa parecer sem resposta). Minha pergunta é basicamente se é bom associar firmemente o segmento à classe Excel.
1128 Jetti

0

Eu separaria sua interface do usuário da sua tarefa em segundo plano usando classes separadas. Isso encoraja a separação de preocupações. O código da interface do usuário e a lógica de negócios não devem ser misturados.


Só para esclarecer, minha turma não toca na interface do usuário. Ele tem dois eventos que permitiriam o que estiver sendo usado para atualizar a interface do usuário, se necessário, mas minha classe por si só não toca na interface do usuário.
Jetti

0

Pelo que me lembro sobre os BackgroundWorkers, eles fornecem vários métodos de conveniência, como a capacidade de enviar atualizações de progresso para a interface do usuário. Não existe uma regra que diga que você não pode usá-lo de uma classe diferente.

Além disso, se você estiver fazendo uma iteração que não exige que os itens sejam processados ​​em uma ordem específica, considere usar o ThreadPool (ou se estiver no .NET 4, use a Biblioteca Paralela de Tarefas ).


Obrigado pela sua resposta. Criei dois eventos na minha classe que serão acionados no progresso (basicamente, agrupando o evento de progresso BackgroundWorker, pois o BackgroundWorker é privado), que envia o progresso para a interface do usuário (barra de progresso).
Jetti
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.