Domanda

C'è un gestita a livello di sistema generatore di numeri sequenziali? DateTime.Now.Ticks non fare perché le operazioni che sto facendo a volte si verificano più di una volta per tick.


Chiarimenti Requisito:

  • Processo agnostico -. Non c'è davvero solo un processo che sarebbe stato Accedendo a questo
  • Performance è fondamentale! Questo viene utilizzato per registrare le impressioni su adServer, che può raggiungere 1k / sec

Si avrebbe bisogno di essere uno dei seguenti:

  • Un numero progressivo di 4 byte che resetta ogni tick
  • A 12-byte numero sequenziale - essenzialmente aggiungendo 4 byte di granularità ad un DateTime
È stato utile?

Soluzione

Nessuno di quelli che sono destinati per questo, ma è possibile utilizzare System.Diagnostics.PerformanceCounter . Si potrebbe anche utilizzare il Registro di sistema, ma avresti bisogno di serializzare lettura / scrittura attraversato i processi.

System.Diagnostics.PerformanceCounter pc 
    = new System.Diagnostics.PerformanceCounter("SeqCounter", "SeqInstance");
long myVal=pc.Increment();

Modifica

Il più penso a questo, credo che questo potrebbe essere una bella soluzione. Incremento aumenterà il contatore 1 tramite un'operazione atomica che dovrebbe funzionare attraversato tutti i processi in un sistema.

Modifica

In base le modifiche, non mi consiglia di utilizzare un contatore di prestazioni. Un contatore delle prestazioni è stato un modo per cordinate attraversato più processi. Io non sono sicuro di come il L'implementazione interna è codificato.

Perché non si può semplicemente utilizzare una variabile statica e incrementarlo? La vostra intenzione di avere per bloccare qualcosa se si desidera che questo sia threadsafe.

System.Threading.Interlocked.Increment

A proposito:. Se si utilizza la versione lunga su un sistema a 32 bit non sarà nessecarilly thread-safe


Modifica per mostrare la fine dell'esecuzione ho usato (DS):

public static class Int32Sequencer
{
    private static Int32 lastSequence = Int32.MinValue;
    private static Object lockObject = new Object();
    public static Int32 GetNextSequence()
    {
        lock (lockObject)
        {
            unchecked { lastSequence++; }
            return lastSequence;
        }
    }
}

Altri suggerimenti

Un GUID è più vicino come si sta andando ad ottenere, ma questi sono "unici" e non necessariamente sequenziale. Se si vuole veramente sequenziale attraverso più processi a livello di sistema, probabilmente si dovrà rotolare il proprio.

EDIT:

Ok, quindi dalle vostre nuove esigenze, ho intenzione di assumere:

  1. Un solo processo ha bisogno di fare il lavoro
  2. Stai aggiungere i dati ad un database

Così qui è quello che mi sento di raccomandare:

  1. Al processo di start-up, interrogare il DB per l'ultimo valore (massimo) (0 se non ne esistono).
  2. Utilizzare una semplice lunga e l'incremento per ogni riga DB. Avete intenzione di voler inserire in lotti a causa della vostra alta velocità di trasmissione dati.

Che dovrebbe farlo. Keep it simple. Questo non ha serrature, un lieve (trascurabili) ha colpito allo start-up, e numeri sequenziali nel vostro DB. Questo algoritmo è anche processo agnotic finché si dispone di un solo processo in esecuzione di esso.

Credo che la cosa più vicina è un GUID, che, come sono sicuro che siete a conoscenza è nel migliore dei casi solo in parte sequenziale.

C'è un articolo qui che fornisce alcuni dettagli per SQL Server: sequenziali GUID in SQL Server Questa tecnica viene utilizzata per ridurre al minimo divisioni di pagina a causa della casualità della GUID di. Forse questo link vi darà alcuni suggerimenti o idee.

Credo che abbiamo bisogno di sapere un po 'di più su ciò che si sta cercando. Può chiarire la tua domanda un po '. In particolare, se il servizio ...

  • necessità di lavorare in tutti i processi, un processo, o di un particolare utente?
  • deve essere il numero unico o solo sequenziale?

In base alla tua domanda sembra che ci siano un paio di diversi elementi si può essere cercando.

Bisogno di un gruppo sequenziale di numeri in tutti i processi del sistema

Per quanto ne so, non tale servizio esiste. Uno dovrebbe essere abbastanza facile da scrivere, ma a farla funzionare in tutti i processi è difficile.

Bisogno di un gruppo sequenziale unico di numeri in tutti i processi del sistema

lieve variazione sulla prima questione. Tale servizio non esiste perché sarebbe impossibile da attuare. Non v'è alcun modo per garantire un numero progressivo univoco utilizzando i tipi di dati built-in, semplicemente perché il valore alla fine di overflow e ti lasciano con un numero duplicato.

bisogno di un metodo di ottenere valori unici nel sistema

Come molti altri utenti hanno menzionato la scelta migliore è un'istanza System.Guid. È possibile creare uno nuovo utilizzando Guid.NewGuid (). Per quasi tutti gli scopi che possono essere considerati unici, ma non sono sequenziali.

Mi piace l'opzione di database semplicemente per la sicurezza. Assicurarsi di installare un server SQL mostro con assegnare di larghezza di banda tra i server con memoria sufficiente però. Un sistema simile a questo è stato realizzato in occasione della prima azienda che ho mai lavorato per (Prima di diventare anche un programmatore) ed era molto rischioso. Si può combattere per scalare questo.

Un'altra opzione sarebbe quella di implementare una funzione Singleton nel codice ... fornito un solo dominio di applicazione verrà chiamando. Può essere un po 'più veloce di fare un viaggio di database. Se invece avete intenzione di essere la registrazione questa roba al database comunque .... Che dire combinando i due ... Eseguire un Singleton per la velocità e quindi scrivere al database quando le risorse lo permettono.

Anche in questo caso, se il requisito sequenziale non è così forte, un GUID sarebbe la soluzione migliore.

Non c'è modo per ottenere una singola serie sequenziale senza bloccare. Non importa quale meccanismo si sta utilizzando per assegnare il valore successivo - un contatore di prestazioni, una variabile statica, qualunque sia -. Quando due thread entrambi hanno bisogno il valore successivo, allo stesso tempo, si deve aspettare dall'altra

La prima cosa che farei è scrivere un programma di test che ha generato un gran numero di fili che ogni ripetutamente chiesto una funzione di incremento di blocco come quello di Daniel Schaffer postato. Che vi permetterà di trovare la soglia in cui l'applicazione inizia a thrash -. Dove è passare più tempo in attesa di Monitor.Enter di fare qualsiasi altra cosa

Se questo risulta essere un problema - e scommetto che se i volumi si sta parlando sono reali, sarà - allora si dovrebbe fare ogni thread mantenere il proprio contatore sequenziale, che si può fare marcando il campo contatore con il ThreadStaticAttribute. È quindi possibile generare identificatori univoci al largo di una combinazione di ID del thread e il contatore.

Questo approccio non funziona se non si sta usando un pool di thread (da quando il contatore muore quando il filo a cui appartiene lo fa). E probabilmente anche voler far parte conteggio di avvio dell'applicazione del ID composto, in modo che non c'è bisogno di scrivere i contatori thread per lo stoccaggio di lunga durata. (Se non si esegue questa operazione, una volta riavviato il server i fili avrebbero iniziare a generare i contatori a zero ancora una volta, e se l'applicazione ha creato un thread con lo stesso ID come istanza in precedenza, si otterrebbe identificatori duplicati.)

Questo ovviamente non è banale scrivere (o, cosa più importante, test), quindi ve lo consiglio senza dimostrando che è necessario prima.

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