Pregunta

He leído y he mirado algunos ejemplos de Threadpooling pero parece que no puedo entenderlo como necesito. Lo que he logrado poner a trabajar no es realmente lo que necesito. Simplemente ejecuta la función en su propio hilo.

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();
}

Lo que estoy tratando de hacer es tener alrededor de 50 hilos (tal vez más) que obtienen datos de PHP serializados que contienen estadísticas de jugador. A partir del usuario 0 hasta un ID de usuario que especifique (300,000). Mi pregunta no es sobre cómo obtener las estadísticas. Sé cómo obtener las estadísticas y leerlas, pero cómo escribo un Threadpool que seguirá obteniendo estadísticas hasta que llegue a 300,000 de ID de usuario sin pisar los dedos de los otros hilos y guarda las estadísticas a medida que las recupera en una base de datos.

¿Fue útil?

Solución

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();
}

Esta es la cosa más simple de hacer. Pero está lejos de ser óptimo. Está utilizando llamadas síncronas, confía en ThreadPool para reducir su tasa de llamadas, no tiene una política de reintento para llamadas fallidas y su aplicación se comportará extremadamente mal en condiciones de error (cuando fallan las llamadas web).

Primero debe considerar el uso de los métodos asíncronos de WebRequest: BeginGetRequestStream (si realiza POST y tiene un cuerpo de solicitud) y / o BeginGetResponse . Estos métodos se escalan mucho mejor y obtendrás un rendimiento más alto por menos CPU (si el back-end puede mantenerse, por supuesto).

Segundo, deberías considerar el auto-manejo. En un proyecto similar utilicé un recuento de solicitudes pendientes. En caso de éxito, cada llamada enviaría 2 llamadas más, con el límite máximo de conteo. En caso de fallo, la llamada no enviaría nada. Si no hay llamadas pendientes, un reintento basado en temporizador envía una nueva llamada cada minuto. De esta manera, solo intenta una vez por minuto cuando el servicio está inactivo, evitando que sus propios recursos giren sin tracción, y aumenta el rendimiento hasta el límite máximo cuando el servicio está activo.

También debe saber que el marco .Net limitará la cantidad de concisiones coherentes que realiza a cualquier recurso. Debe encontrar su destino ServicePoint y cambiar el ConnectionLimit de su valor predeterminado (2 ) al valor máximo en el que está dispuesto a acelerar.

Acerca de la parte de actualización de la base de datos, hay muchas variables en juego y muy poca información para dar algún consejo significativo. Un consejo general sería usar métodos asincrónicos en la llamada de la base de datos también, dimensionar el grupo de conexiones yoru para permitir su límite de aceleración, asegúrese de que sus actualizaciones usen la ID del jugador como clave para que no se bloquee la actualización del mismo registro desde diferentes hilos .

Otros consejos

¿Cómo determinas el ID de usuario? Una opción es segmentar todos los subprocesos para que el subproceso X trate con ID de 0 a N, y así sucesivamente, como una fracción de cuántos subprocesos tiene.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top