Por favor ver más abajo pseudo código

//Single or multiple Producers produce using below method
    void Produce(object itemToQueue)
    {
        concurrentQueue.enqueue(itemToQueue);
        consumerSignal.set;
    }

    //somewhere else we have started a consumer like this
    //we have only one consumer
    void StartConsumer()
    {
        while (!concurrentQueue.IsEmpty())
        {
            if (concurrentQueue.TrydeQueue(out item))
            {
                //long running processing of item
            }
        }
        consumerSignal.WaitOne();
    }

¿Cómo puedo puerto este patrón que he utilizado desde tiempos inmemoriales para uso taskfactory tareas creadas y la nueva señalización de las características de la red 4. En otras palabras, si alguien fuera a escribir este patrón de uso de red 4 ¿cómo sería ? Pseudo código está bien. Iam ya está utilizando .net 4 concurrentQueue como se puede ver. ¿Cómo puedo utilizar una tarea y posiblemente el uso de algunos de los nuevos mecanismo de señalización si es posible. gracias

Solución a mi problema, a continuación gracias a Jon/Dan. Dulce.
No hay manual de señalización o while(true) o tiempo(itemstoProcess) tipo de bucles como en los viejos tiempos

//Single or multiple Producers produce using below method
 void Produce(object itemToQueue)
 {
     blockingCollection.add(item);
 }

 //somewhere else we have started a consumer like this
 //this supports multiple consumers !
 task(StartConsuming()).Start; 

 void StartConsuming()
 {
     foreach (object item in blockingCollection.GetConsumingEnumerable())
     {
                //long running processing of item
     }
 }

cancellations are handled using cancel tokens
  • Una muy buena (porque es paso por paso) explicación y ejemplo aquí.
  • Hola Gullu, por favor, eche un vistazo a este código. Es un simple ejemplo de trabajo en el uso de la BlockingCollection<T> para el Productor-Consumidor patrones.
InformationsquelleAutor Gullu | 2011-06-28

3 Comentarios

  1. 23

    Utilizaría BlockingCollection<T>. Hay un ejemplo en la documentación.

    Que la clase está diseñada específicamente para hacer de este trivial.

    • thx. Pero Iam ya utilizando un concurrentQ
    • Que bien que envuelva a que en un BlockingCollection<T>. Si usted insiste en hacer las cosas de forma directa, se va a terminar, básicamente, la repetición de un montón de código en BlockingCollection<T> – ¿por qué reinventar la rueda?
    • Jon ha dado la canónica .Net 4 solución para el productor problema de consumo. De MSDN: «Proporciona el bloqueo y la delimitación de las capacidades para el hilo de seguridad de las colecciones que implementan IProducerConsumerCollection<T>.»
    • Jon, si se desplaza a la parte inferior de la página en la página de msdn que se refieren a los de arriba, verás a continuación el código. Esto es tan cojo en comparación con la antigua señalización he mostrado en mi post anterior. No estás de acuerdo ? // Consumir bc while (true) de la Consola.WriteLine(ac.Tomar()); } catch (InvalidOperationException) { // OIE significa que Tomar() fue llamado en un formulario de recogida de la Consola.WriteLine («¡Eso es Todo!»); }
    • El bloqueo de la colección no proporciona ninguna señalización para el consumidor, a menos que el consumidor se va a encuestar en blockingcollection.IsCompleted/IsAddingCompleted. En el clásico patrón que he publicado un productor añade a la cola, las señales de que el consumidor y se hace. Con un bloqueo de coll podemos marcar el coll como completedadding que luego se pone en un estado donde más elementos no se pueden añadir hasta que el consumidor deques todos los elementos.
    • Usted no necesita encuesta – usted sólo tiene que utilizar Take y bloquea hasta que haya un elemento de la lista. Puede especificar una limitada capacidad, si se desea que el productor para bloquear hasta hay espacio para un nuevo elemento en la cola.
    • Todavía no entiendo cómo un consumidor puede ser notificado cuando se agregan elementos. Mi post tiene alrededor de 10 líneas de código de pseudo. Puede usted por favor, puerto de (pseudo código fino) y después aquí. Esa fue mi verdadera pregunta de todos modos. Línea de fondo es que puedo conseguir que funcione mediante el bloqueo de la colección, la tarea de fábrica, etc, pero el clásico patrón de uso de las señales como se muestra se ve mucho más limpio. gracias
    • la Tome de la llamada se bloquea hasta que un elemento está disponible (es un blocking de la colección), por lo que la espera de una señal que pasa como un detalle de implementación dentro de Tomar.
    • Jon/Dan Finalmente lo consiguió. Voy a actualizar mi post para mostrar el nuevo/viejo patrón de lado a lado. Cualquier persona que puede mejorar, por favor editar el post. gracias
    • Estoy tratando de implementar el simple BlockingCollection de uso sin un while(true) y TryTake() dentro de una Tarea. Yo iba a usar GetConsumingEnumerable (), pero esto me está matando … por msdn.microsoft.com/en-us/library/dd460684%28v=vs.110%29.aspx «…no Hay ninguna garantía de que los artículos que se enumeran en el mismo orden en que se agregan por el productor hilos.» ¿Cuál es el punto de tener un ConcurrentQUEUE si no puedo enumerar y garantizar el orden? Necesito tener los elementos que se procesan de forma secuencial. Me estoy perdiendo algo?
    • Tengo la sospecha de que se está perdiendo que ConcurrentQueue no es el único concurrente de la colección. Sospecho que con ConcurrentQueue estás bien.
    • skeet sé que hay otras colecciones simultáneas. Yo hubiera esperado que la documentación de MSDN para haber hecho esa advertencia con respecto a la cola.

  2. 11

    Su segundo bloque de código se ve mejor. Pero, a partir de un Task y, a continuación, inmediatamente, a la espera de que es inútil. Simplemente llame a Take y luego procesar el elemento que se devuelve directamente en el consumo de hilo. Que es cómo el productor-consumidor patrón está destinado a ser hecho. Si usted piensa que el procesamiento de los elementos de trabajo es lo suficientemente intenso como para justificar más a los consumidores, a continuación, por todos los medios de inicio más a los consumidores. BlockingCollection es seguro varios productores y varios consumidores.

    public class YourCode
    {
      private BlockingCollection<object> queue = new BlockingCollection<object>();
    
      public YourCode()
      {
        var thread = new Thread(StartConsuming);
        thread.IsBackground = true;
        thread.Start();
      }
    
      public void Produce(object item)
      {
        queue.Add(item);
      }
    
      private void StartConsuming()
      {
        while (true)
        {
          object item = queue.Take();
          //Add your code to process the item here.
          //Do not start another task or thread. 
        }
      }
    }
    • ¿por qué no empezamos otra tarea o hilo en StartConsuming?
    • Que sería bien por sí mismo. Lo que no está bien, está empezando otra de las tareas y, a continuación, esperar en él. Que sería inútil.
    • Gracias por la aclaración
    • Excelente ejemplo, puedo sugerir la adición de la utilización de un cancellationtoken para la integridad
  3. 1

    He usado un patrón antes de que crea una especie de ‘on-demand’ cola de consumo (basado en el consumo de un ConcurrentQueue):

            private void FireAndForget(Action fire)
            {
                _firedEvents.Enqueue(fire);
                lock (_taskLock)
                {
                    if (_launcherTask == null)
                    {
                        _launcherTask = new Task(LaunchEvents);
                        _launcherTask.ContinueWith(EventsComplete);
                        _launcherTask.Start();
                    }
                }
            }
    
            private void LaunchEvents()
            {
                Action nextEvent;
    
                while (_firedEvents.TryDequeue(out nextEvent))
                {
                    if (_synchronized)
                    {
                        var syncEvent = nextEvent;
                        _mediator._syncContext.Send(state => syncEvent(), null);
                    }
                    else
                    {
                        nextEvent();                        
                    }
    
                    lock (_taskLock)
                    {
                        if (_firedEvents.Count == 0)
                        {
                            _launcherTask = null;
                            break;
                        }
                    }
                }
            }
    
            private void EventsComplete(Task task)
            {
                if (task.IsFaulted && task.Exception != null)
                {
                     //Do something with task Exception here
                }
            }
    • thx. Pero Iam con la esperanza de red 4 nuevos tpl pfx debe hacer el clásico patrón que he publicado más fáciles de mantener/entender. Su enfoque es una exageración para mí.
    • Si su objetivo principal es la facilidad de uso, Jon respuesta es la mejor; la BlockingCollection está diseñado específicamente para este patrón común (con una simple llamada de bloqueo para Tomar y soporte integrado para el nuevo sistema de Cancelación.)

Dejar respuesta

Please enter your comment!
Please enter your name here