È "sbagliato" / cattivo design mettere un thread / lavoratore in background in una classe?


15

Ho una classe che leggerà da Excel (C # e .Net 4) e in quella classe ho un lavoratore in background che caricherà i dati da Excel mentre l'interfaccia utente può rimanere reattiva. La mia domanda è la seguente: è un cattivo progetto avere un lavoratore in background in una classe? Devo creare la mia classe senza di essa e utilizzare un lavoratore in background per operare su quella classe? Non riesco a vedere alcun problema nel creare la mia classe in questo modo, ma poi sono di nuovo un principiante, quindi ho pensato che mi sarei assicurato prima di continuare.

Spero che questa domanda sia pertinente qui perché non penso che dovrebbe essere su StackOver mentre il mio codice funziona, questo è solo un problema di progettazione.


3
perché pensi che potrebbe essere sbagliato?
Alb

1
@Alb - è difficile da dire. Il mio codice funziona e soddisfa le mie esigenze, tuttavia, sto programmando di utilizzarlo in un progetto che realizzerò open source. Voglio assicurarmi che il mio codice non "funzioni" e in realtà sia ben progettato.
Jetti,

Risposte:


21

Devo creare la mia classe senza di essa e utilizzare un lavoratore in background per operare su quella classe?

Si, dovresti. E ti dirò perché - stai violando il principio di responsabilità singola . Abbinando strettamente la classe che accede al documento Excel con il modo in cui accede al documento Excel, si elimina la possibilità per il codice "controller" (qualsiasi codice che lo utilizza) di farlo in modo diverso. Quanto diverso, potresti chiedere? Cosa succede se il codice del controller ha due operazioni che richiedono molto tempo ma vuole che siano sequenziali? Se hai concesso al controller la possibilità di gestire il threading, può eseguire entrambe le attività di lunga durata insieme in un thread. Cosa succede se si desidera accedere al documento Excel da un contesto non UI e non è necessario che sia sottoposto a thread?

Spostando la responsabilità del threading verso il chiamante, consenti una maggiore flessibilità del tuo codice, rendendolo più riutilizzabile.


2
+1 per aver risposto alla domanda effettiva che è stata posta e aver risposto bene.
Adam Lear

+1 - Grazie Nemi. Hai risposto alla mia domanda immediatamente, lo apprezzo. Lo tirerò fuori dalla mia classe e lo inserirò in una nuova classe, grazie ancora!
Jetti,

@Nemi - quindi sarebbe accettabile se creassi un altro metodo che avrebbe un carico sincrono e quindi un metodo asincrono? O sarebbe solo meglio avere un metodo di caricamento sincrono e poi passare da lì?
Jetti,

1
Personalmente non avrei un metodo di sincronizzazione e un metodo asincrono. Stai ancora accoppiando le responsabilità. Ho lavorato con questo esatto problema molte volte. Quello che ho fatto è stato creato un TaskController modellato su SwingWorker, ma con codice specifico per la nostra app. TaskController ha fatto cose come aggiornare una barra di avanzamento, cambiare il cursore del mouse, ecc. Potrebbe sembrare che il codice della piastra della caldaia debba sempre creare un TaskController per effettuare chiamate, ma alla fine il codice è più robusto e più gestibile.
Nemi,

Grazie Nemi! Vorrei poterti votare di nuovo perché hai sicuramente risposto alla mia domanda e mi hai indicato la giusta direzione. Grazie ancora!!
Jetti

3

È consigliabile progettare le operazioni dell'interfaccia utente in un thread separato dalle attività in background. Altrimenti l'interfaccia utente non risponde quando l'applicazione è occupata.

Se riesci a separare la parte che funziona nel thread in background alla sua stessa classe, il codice sarà più pulito.


1
Sebbene corretto, da come ho letto la sua domanda non ha problemi a comprendere questo punto.
Nemi,

Mi dispiace se la mia domanda è stata male interpretata. So che separare l'interfaccia utente e le attività in background è una buona progettazione (se non necessario, il mio file excel di prova è di oltre 8k righe e farebbe sembrare il programma non rispondente). La mia domanda è fondamentalmente è bene accoppiare strettamente il thread con la classe Excel.
Jetti,

0

Vorrei separare la tua UI dall'attività in background usando classi separate. Ciò incoraggia la separazione delle preoccupazioni. Il codice dell'interfaccia utente e la logica aziendale non devono essere mescolati.


Per essere chiari, la mia classe non tocca l'interfaccia utente. Ha due eventi che consentirebbero qualsiasi cosa lo stia utilizzando per aggiornare l'interfaccia utente, se necessario, ma la mia classe in sé non tocca l'interfaccia utente.
Jetti

0

Da ciò che ricordo di BackgroundWorkers è che forniscono una serie di metodi di convenienza come la possibilità di inviare aggiornamenti di avanzamento all'interfaccia utente. Non ci sono regole che dicono che non puoi usarlo da una classe diversa.

Inoltre, se stai eseguendo iterazioni che non richiedono l'elaborazione di elementi in un ordine specifico, prendi in considerazione l'utilizzo di ThreadPool (o se sei su .NET 4, utilizza la Libreria parallela di attività ).


Grazie per la risposta. Ho creato due eventi nella mia classe che si innescheranno sui progressi (fondamentalmente avvolgendo l'evento progress di BackgroundWorker, poiché BackgroundWorker è privato) che invia i progressi all'interfaccia utente (barra di avanzamento).
Jetti,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.