C # Il modo migliore per callback un'applicazione client con risultati intermedi da un pool di thread

StackOverflow https://stackoverflow.com/questions/991957

Domanda

Ho scritto una libreria C #, che ha un metodo per contare le parole da più passaggi del testo in Parrallel. I passaggi di testo sono dati come flussi di caratteri in cui v'è un ritardo casuale ogni getnextchar() tempo è chiamato. Il mio metodo biblioteca deve prendere una serie di questi flussi di caratteri e restituire un conteggio delle parole-frequenza combinato. Per fare questo ho una struttura di dati di parola-frequenza in sicurezza comune e un filo di leggere ogni flusso di caratteri e aggiornare la raccolta condivisa. Quando tutti i thread hanno completato poi torno la struttura dei dati per l'applicazione client.

L'applicazione client ha bisogno di risultati intermedi della parola combinata contando ogni 10 secondi. Per fare questo io uso un delegato di richiamare il cliente ogni 10 secondi con i risultati fino a tutti i thread di lavoro hanno completato, dopo di che ho restituire i risultati finali per il cliente.

Il mio problema è che quando ho callback del client con i risultati intermedi che devo bloccare la mia struttura dati condivisa e attendere che l'applicazione client per tornare dalla richiamata prima che io possa non-bloccarlo. Quando la richiamata sta eseguendo tutti i thread sono bloccati in attesa del blocco sulla struttura dati. Ciò non sembra una cosa sensata da fare, perché non penso che dovrei contare o fidarsi del codice del client di restituire tempestivamente o addirittura per niente. Tuttavia essi unico altro modo che posso pensare di farlo, che non si basa sul codice del client è quello di fare una copia o un'istantanea della mia struttura dei dati e passare che per il cliente attraverso la richiamata. Questo è a scapito della memoria e di calcolo ma una volta che la copia è fatta i lavoratori possono continuare l'aggiornamento della raccolta condivisa e la richiamata può fare quello che vuole.

La mia domanda è duplice:

1) che è il male minore, consentendo la possibilità di un'implementazione cattivo client callback per bloccare gli operai, o periodicamente eseguendo un'operazione costosa.

2) C'è un modo per risolvere questo problema che pretende molto fare uno di quanto sopra?

È stato utile?

Soluzione

Mi sarebbe sicuramente dire che il maggiore dei due mali si fida del cliente. Richiamare in codice sconosciuto mentre si tiene un blocco è una ricetta per il deadlock e scenari peggiori. Sì, si pagherà un overhead per scattare un'istantanea della vostra struttura e restituirlo. Ma la memoria aggiuntiva per un'istantanea superiore al rischio di gridare mentre si tiene un blocco.

Ho eseguito in situazioni simili e finora l'istantanea non è stato un problema. Se lo è, però, si possono trovare diversi modi per risolvere questo. Tra cui l'aumento della frequenza con cui si chiama il cliente che ridurrà la quantità di dati che si hanno a snapshot in un dato momento.

Un altro modo per aggirare questo è quello di utilizzare una struttura dati immutabili. Quando si è pronti a parlare con il cliente semplicemente rompere la versione corrente e consegnarlo al cliente. Permettete ai vostri thread in background per iniziare a costruire una nuova.

Altri suggerimenti

Recentemente ho incontrato un problema come questo durante la scrittura di una libreria - non era esattamente lo stesso, ma la domanda di fondo era la stessa - quanto ci si può fidare vostro il client che utilizza la libreria. Che cosa fate quando si può ottenere prestazioni migliori se si può fare affidamento sul client per fare una certa cosa?

Quello che abbiamo finito per fare era avere due percorsi di codice e una bandiera il cliente potrebbe impostare il nostro oggetto per indicare quale strada prendere. In sostanza, si trattava di un flag 'puoi fidarti di me'. Se non è stato impostato (l'impostazione predefinita), la biblioteca avrebbe assunto è che fare con un cliente che non poteva fidarsi, e mai dare al cliente un riferimento diretto alle strutture di dati interne - è sempre ottenuto una copia. Tuttavia, se il client impostato quella bandiera, allora avrebbero ottenere l'accesso diretto alla struttura reale e hanno dovuto seguire le regole ci eravamo prefissati (documentati sia la bandiera e la funzione di accesso).

Tuttavia, nel tuo caso (eventi), sembra che tu avresti avuto un'altra scelta - due eventi diversi. Il 'normale' uno (che i cloni delle strutture prima di dare al cliente), e quella 'avanzato' che contiene il blocco e gli dà la struttura reale di esaminare. Basta assicurarsi che sia chiaramente documentato che se si utilizza quella avanzata, non è possibile utilizzare tale riferimento, tranne durante il gestore di eventi, ed è meglio essere veloce, perché si sta alzando il trattamento, mentre farlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top