varios tiempo programacion parametros multihilos metodos hilos ejemplo ejecutar creacion con cierto cada c# multithreading .net-2.0

tiempo - Acelerar el bucle usando multihilo en C#(Pregunta)



metodos de hilos c# (6)

Imagina que tengo una función que atraviesa un millón / billón de cuerdas y comprueba muy poco en ellas.

f.ex:

foreach (String item in ListOfStrings) { result.add(CalculateSmth(item)); }

consume mucho tiempo, porque CalculateSmth es una función que consume mucho tiempo.

Quiero preguntar: ¿cómo integrar multihilo en este proceso?

f.ex: quiero activar 5 hilos y cada uno de ellos arroja algunos resultados, y eso continúa hasta que la lista tenga elementos.

Tal vez cualquiera pueda mostrar algunos ejemplos o artículos.

Olvidé mencionar que lo necesito en .NET 2.0


La primera pregunta que debe responder es si debe usar el enhebrado

Si su función CalculateSmth () está básicamente vinculada a la CPU, es decir, tiene un uso intensivo de la CPU y básicamente no usa I / O, entonces me resulta difícil ver el punto de uso de los hilos, ya que los hilos competirán por el mismo recurso , en este caso, la CPU.

Si su CalculateSmth () está usando tanto CPU como E / S, entonces podría ser un punto en el uso del enhebrado.

Estoy totalmente de acuerdo con el comentario de mi respuesta. Hice una suposición errónea de que estábamos hablando de una sola CPU con un núcleo, pero en estos días tenemos CPU multinúcleo, mi mal.


Necesita dividir el trabajo que desea hacer en paralelo. Aquí hay un ejemplo de cómo puede dividir el trabajo en dos:

List<string> work = (some list with lots of strings) // Split the work in two List<string> odd = new List<string>(); List<string> even = new List<string>(); for (int i = 0; i < work.Count; i++) { if (i % 2 == 0) { even.Add(work[i]); } else { odd.Add(work[i]); } } // Set up to worker delegates List<Foo> oddResult = new List<Foo>(); Action oddWork = delegate { foreach (string item in odd) oddResult.Add(CalculateSmth(item)); }; List<Foo> evenResult = new List<Foo>(); Action evenWork = delegate { foreach (string item in even) evenResult.Add(CalculateSmth(item)); }; // Run two delegates asynchronously IAsyncResult evenHandle = evenWork.BeginInvoke(null, null); IAsyncResult oddHandle = oddWork.BeginInvoke(null, null); // Wait for both to finish evenWork.EndInvoke(evenHandle); oddWork.EndInvoke(oddHandle); // Merge the results from the two jobs List<Foo> allResults = new List<Foo>(); allResults.AddRange(oddResult); allResults.AddRange(evenResult); return allResults;


No es que tenga buenos artículos aquí en este momento, pero lo que quiere hacer es algo a lo largo de Producer-Consumer con Threadpool.

Los productores recorren y crean tareas (que en este caso podrían ser simplemente poner en cola los elementos en una lista o pila). Los consumidores son, por ejemplo, cinco hilos que leen un elemento de la pila, lo consumen al calcularlo y luego lo almacenan en otro lugar.

De esta forma, el multihilo se limita a esos cinco hilos, y todos tendrán que trabajar hasta que la pila esté vacía.

Cosas para pensar:

  • Ponga protección en la lista de entrada y salida, como un mutex.
  • Si el orden es importante, asegúrese de que se mantenga el orden de salida. Un ejemplo podría ser almacenarlos en SortedList o algo así.
  • Asegúrese de que CalculateSmth es seguro para subprocesos, que no utiliza ningún estado global.

Tenga en cuenta que la concurrencia no le proporciona mágicamente más recursos. Necesita establecer lo que está disminuyendo CalculateSmth hacia abajo.

Por ejemplo, si está vinculado a la CPU (y está en un solo núcleo), entonces la misma cantidad de ticks de la CPU irá al código, ya sea que los ejecute secuencialmente o en paralelo. Además, obtendrás un poco de sobrecarga al administrar los hilos. El mismo argumento se aplica a otras restricciones (por ejemplo, E / S)

Solo obtendrá ganancias de rendimiento si CalculateSmth deja libre el recurso durante su ejecución, que podría ser utilizado por otra instancia. Eso no es raro. Por ejemplo, si la tarea implica IO seguido de algunas cosas de la CPU, entonces el proceso 1 podría estar haciendo las cosas de la CPU mientras que el proceso 2 está haciendo la IO. Como señala mat, una cadena de unidades de productores y consumidores puede lograr esto, si tiene la infraestructura.


Las extensiones paralelas son geniales, pero esto también se puede hacer simplemente usando el grupo de subprocesos de la siguiente manera:

using System.Collections.Generic; using System.Threading; namespace noocyte.Threading { class CalcState { public CalcState(ManualResetEvent reset, string input) { Reset = reset; Input = input; } public ManualResetEvent Reset { get; private set; } public string Input { get; set; } } class CalculateMT { List<string> result = new List<string>(); List<ManualResetEvent> events = new List<ManualResetEvent>(); private void Calc() { List<string> aList = new List<string>(); aList.Add("test"); foreach (var item in aList) { CalcState cs = new CalcState(new ManualResetEvent(false), item); events.Add(cs.Reset); ThreadPool.QueueUserWorkItem(new WaitCallback(Calculate), cs); } WaitHandle.WaitAll(events.ToArray()); } private void Calculate(object s) { CalcState cs = s as CalcState; cs.Reset.Set(); result.Add(cs.Input); } } }


Podría probar las extensiones paralelas (parte de .NET 4.0)

Estos te permiten escribir algo como:

Parallel.Foreach (ListOfStrings, (item) => result.add(CalculateSmth(item)); );

Por supuesto, result.add debería ser seguro para subprocesos.