2012-05-16 10 views
5

Soy un poco nuevo en Multi-Threading y solo he jugado con él en el pasado. Pero tengo curiosidad si es posible tener una lista de matrices de bytes en un hilo principal y todavía ser capaz de agregar a esa lista al crear el nuevo conjunto de bytes en un hilo separado. Además, utilizaré un bucle for-each que irá a través de una lista de formularios que se usarán para analizar en la matriz de bytes. Así que, básicamente, un pseudo código sería así ...¿Cómo agregar a una lista al usar Multi-Threading?

reports = new List(); 

foreach (form in forms) 
{ 
    newReport = new Thread(ParseForm(form)); 
    reports.Add(newReport); 

} 

void ParseForm(form) 
{ 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    return newArray; 
} 

Esperemos que el pseudo-código anterior hace algún sentido. Si alguien pudiera decirme si esto es posible y apuntarme en la dirección de un buen ejemplo, estoy seguro de que puedo descifrar el código real.

+0

Olvidé mencionar que el servicio web usa .Net 3.5, por lo que no creo que haya tareas disponibles. – jhorton

Respuesta

3

Si necesita acceder a una colección de múltiples hilos, deberías o sincronización de uso, o utilizar un SynchronizedCollection si su. La versión NET es 3.0 o superior.

Aquí es una manera de hacer la colección accesible a su hilo:

SynchronizedCollection reports = new SynchronizedCollection(); 

foreach (form in forms) { 
    var reportThread = new Thread(() => ParseForm(form, reports)); 
    reportThread.Start(); 
} 

void ParseForm(Form form, SynchronizedCollection reports) { 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    reports.Add(newArray); 
} 

Si usted está en .NET 4 o posterior, una alternativa mucho mejor a la gestión de sus hilos manualmente es presentada por varias clases de la System.Threading.Tasks espacio de nombres. Considere la posibilidad de explorar esta alternativa antes de decidir sobre su implementación de enhebrado.

+0

Gracias, tendré que probar SynchronizedCollection ya que todavía estoy en 3.5. – jhorton

+0

¿Debo establecer una referencia para SynchronizedCollection? Tengo las declaraciones de uso para Collections.Genereric y Threading. Y comprobé que está usando 3.5, pero no obtengo una colección sincronizada. – jhorton

+0

@jhorton Necesita agregar una referencia a 'System.ServiceModel'. – dasblinkenlight

0

Why is enumerate files returning the same file more than once?

comprobar que fuera. Muestra que creo exactamente lo que quieres hacer.

Crea una lista en el hilo principal y luego la agrega desde un hilo diferente. tu vas a necesitar

using System.Threading.Tasks 

-

Files.Clear(); //List<string> 

Task.Factory.StartNew(() => 
{ 
     this.BeginInvoke(new Action(() => 
     { 
      Files.Add("Hi"); 
     })); 
}); 
+1

Funciona solo si ** this ** es un System.Windows.Forms.Control (o clases derivadas). No es un mecanismo de sincronización sino una forma de interactuar con la interfaz de usuario desde otros hilos. –

+0

No puedo discutir eso. –

2

En antes de que nos dimos cuenta que era .Net 3.5, tenga como referencia en .Net 4

Si usted no necesita ningún orden dentro de la lista, una "solución" fácil es usar la clase ConcurrentBag<T> en lugar de una lista. Si necesita más pedido, también hay una colección ConcurrentQueue<T>.

Si realmente necesita algo más personalizado, puede implementar su propia colección de bloqueo utilizando BlockingCollection <T>. Here's a good article sobre el tema.

También puede utilizar Parallel.Foreach para evitar la creación de hilos explícita también:

private void ParseForms() 
{ 
    var reports = new ConcurrentBag<byte[]>(); 
    Parallel.ForEach(forms, (form) => 
           { 
            reports.Add(ParseForm(form)); 
           }); 

} 

private byte[] ParseForm(form) 
{ 
    newArray = new byte[]; 
    newArray = Convert.ToBytes(form); 
    return newArray; 
} 
+0

¿Es el ConcurrentBag solo 4.0 y superior? – jhorton

+0

Sí, acabo de ver su nota también. Esto es ridículamente fácil en .Net 4.0 si puede usarlo. –

+0

Tengo que estar de acuerdo contigo allí. No estoy seguro de por qué aún no han actualizado este servicio a 4.0. Todo lo demás lo está usando. – jhorton

0

A continuación se muestra una simple Colección de bloqueo (como una cola solamente) que acabo de actualizar ya que no tiene acceso a C# 4.0. Probablemente sea menos eficiente que las colecciones simultáneas 4.0, pero debería funcionar bastante bien. No volví a implementar todos los métodos Queue, simplemente en cola, dequeue y peek. Si necesita a otros y no puede entender cómo se implementarían, solo mencioneslo en los comentarios.

Una vez que tenga la colección de bloqueo de trabajo, puede simplemente agregarla desde los hilos del productor y eliminarla mediante los hilos del consumidor.

public class MyBlockingQueue<T> 
{ 
    private Queue<T> queue = new Queue<T>(); 
    private AutoResetEvent signal = new AutoResetEvent(false); 
    private object padLock = new object(); 

    public void Enqueue(T item) 
    { 
     lock (padLock) 
     { 
      queue.Enqueue(item); 
      signal.Set(); 
     } 
    } 

    public T Peek() 
    { 
     lock (padLock) 
     { 
      while (queue.Count < 1) 
      { 
       signal.WaitOne(); 
      } 

      return queue.Peek(); 
     } 
    } 

    public T Dequeue() 
    { 
     lock (padLock) 
     { 
      while (queue.Count < 1) 
      { 
       signal.WaitOne(); 
      } 

      return queue.Dequeue(); 
     } 
    } 
}