Domanda

Ho letto e guardato alcuni esempi di Passaggi thread, ma non riesco proprio a capirlo nel modo in cui ho bisogno. Quello che riesco a far funzionare non è proprio quello di cui ho bisogno. Esegue semplicemente la funzione nel proprio thread.

public static void Main()
    {
        while (true)
        {
            try
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
                Console.WriteLine("ID has been queued for fetching");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
            }
            Console.ReadLine();
        }
    }

public static void Process(object state)
{

    var s = StatsFecther("byId", "0"); //returns all player stats
    Console.WriteLine("Account: " + s.nickname);
    Console.WriteLine("ID: " + s.account_id);
    Console.ReadLine();
}

Quello che sto cercando di fare è avere circa 50 thread (forse più) che raccolgono dati php serializzati contenenti statistiche del giocatore. A partire dall'utente 0 fino a un ID utente che ho specificato (300.000). La mia domanda non è su come recuperare le statistiche che so come ottenere le statistiche e leggerle, ma come scrivo un Threadpool che continuerà a recuperare le statistiche fino a raggiungere il 300.000 ° ID utente senza calpestare le dita degli altri thread e salva le statistiche mentre le recupera in un database.

È stato utile?

Soluzione

static int _globalId = 0;
public static void Process(object state)
{    
  // each queued Process call gets its own player ID to fetch
  processId = InterlockedIncrement(ref _globalId); 
  var s = StatsFecther("byId", processId); //returns all player stats 

  Console.WriteLine("Account: " + s.nickname);    
  Console.WriteLine("ID: " + s.account_id);    
  Console.ReadLine();
}

Questa è la cosa più semplice da fare. Ma è tutt'altro che ottimale. Stai utilizzando chiamate sincrone, ti affidi al ThreadPool per limitare la tua velocità di chiamata, non hai una politica di tentativi per le chiamate non riuscite e la tua applicazione si comporterà estremamente male in condizioni di errore (quando le chiamate web non riescono).

Per prima cosa dovresti considerare di usare i metodi asincroni di WebRequest: BeginGetRequestStream (se POST e disponi di un corpo di richiesta) e / o BeginGetResponse . Questi metodi si adattano molto meglio e otterrai un throughput più elevato per meno CPU (se il back-end può tenere il passo ovviamente).

Secondo, dovresti considerare l'auto-throttling. Su un progetto simile ho usato un conteggio delle richieste in sospeso. In caso di successo, ogni chiamata inoltrerebbe altre 2 chiamate, limitate al conteggio di limitazione. In caso di fallimento, la chiamata non inviava nulla. Se nessuna chiamata è in sospeso, un nuovo tentativo basato sul timer invia una nuova chiamata ogni minuto. In questo modo si tenta solo una volta al minuto quando il servizio è inattivo, risparmiando le proprie risorse dalla rotazione senza trazione e si aumenta il throughput fino al limite massimo quando il servizio è attivo.

Dovresti anche sapere che il framework .Net limiterà il numero di connessioni simultanee che fa a qualsiasi risorsa. È necessario trovare la destinazione ServicePoint e modificare ConnectionLimit dal suo valore predefinito (2 ) al valore massimo che sei disposto a limitare.

Per quanto riguarda la parte di aggiornamento del database, ci sono molte variabili in gioco e troppe informazioni insufficienti per dare consigli significativi. Alcuni consigli generali sarebbero utilizzare anche metodi asincroni nella chiamata al database, dimensioni yoru pool di connessioni per consentire il limite massimo, assicurarsi che gli aggiornamenti utilizzino l'ID giocatore come chiave in modo da non bloccarsi sull'aggiornamento dello stesso record da thread diversi .

Altri suggerimenti

Come si determina l'ID utente? Un'opzione è quella di segmentare tutti i thread in modo che il thread X gestisca gli ID da 0 - N e così via, come una frazione di quanti thread hai.

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