2

I have this Class:

public class PCQueue : IDisposable
{
  public delegate void OnFileAddDelegate(string file);
  public event OnFileAddDelegate OnFileAddEventHandler;
  BlockingCollection<Action> _taskQ = new BlockingCollection<Action>(); 
  public PCQueue (int workerCount)
  {
    // Create and start a separate Task for each consumer:
    for (int i = 0; i < workerCount; i++)
      Task.Factory.StartNew (Consume);
  }

  public void Dispose() { _taskQ.CompleteAdding(); }

  public void EnqueueTask (Action action) { _taskQ.Add (action); }

  void Consume()
  {
    // This sequence that we’re enumerating will block when no elements
    // are available and will end when CompleteAdding is called. 
    foreach (Action action in _taskQ.GetConsumingEnumerable())
      action();     // Perform task.
  }
}

And i have string[] that i want to add into my Queue and after that i want my Consume() get this files in order to processing.

string[] files;

PCQueue pq = new PCQueue(1);
foreach (string item in files)
    pq.EnqueueTask(item);

i have this error: cannot convert from 'string' to 'System.Action'

After i put file from my Queue i am check this file:

Checker checker = new Checker ();
string result = Checker.Check(my file from the Queue);
if (result != null && OnFileAddEventHandler != null)
    OnFileAddEventHandler(result);

And if this file is OK i fired up event to my form

  • Surely the queue should contain the data, not the tasks? – Matthew Watson Aug 29 '14 at 08:26
  • @MatthewWatson Nope, seems like the whole point is to process a collection of files with a predefined number of workers, so either the processing `Action` is stored in the queue, or it is a queue of `Action`s. – AndreySarafanov Aug 29 '14 at 08:46
  • @AndreySarafanov In that case you'd just create an array of tasks and use Parallel.Invoke() to start them, and use a BlockingCollection for the work items. – Matthew Watson Aug 29 '14 at 09:07

1 Answers1

0

If i understand your intent right, you don't need to add a param to your Action, what you need is to change the way you call the EnqueueTask method. For example if you want to enqueue the execution of a ProcessFile(string filename) method, you have to change your code to this:

foreach (string item in files)
{
    string filename = item;
    pq.EnqueueTask(() => ProcessFile(filename));
}

The reason to make the filename variable is to avoid closing over a foreach loop variable, which can be harmful depending on C# version you use, as further explained in this brilliant article.

UPD.: You seem to misunderstand what the PCQueue class does. Its job is not to store the filenames for you, but to store Actions that you want to do and then execute all of them via the Consume() method. That actions do not have to be related to files at all, they can be anything.

But i don't really thing that PCQueue is needed for your task. The way you use it, it is not more efficient that just looping over your files:

Checker checker = new Checker ();
foreach (string item in files) 
{
    string result = Checker.Check(my file from the Queue);
    if (result != null && OnFileAddEventHandler != null) 
    {
        OnFileAddEventHandler(result);
    }
}
AndreySarafanov
  • 804
  • 5
  • 20
  • 2
    shouldn't it be `Action` ? – Marco Aug 29 '14 at 08:15
  • @Serv Maybe i understood the question the wrong way, but it seems like maya remetz wants to add a collection of `string`s to the `PCQueue ` class, so that each element in the `_taskQ ` is called with a corresponding parameter from that collection. – AndreySarafanov Aug 29 '14 at 08:21
  • And when call to EnqueueTask what to do ? i have string[] arr and inside the foreach loop i just pass item and cannot convert string to Action – maya remetz Aug 29 '14 at 08:21
  • Can i use string param = action.ToString(); ??? – maya remetz Aug 29 '14 at 08:28
  • What's is ProcessFile ? the compiler cannot find it – maya remetz Aug 29 '14 at 08:37
  • @mayaremetz It is just a method name that i came up with. You want to do **something** with that files, right? That **something** is most likely a method that accepts the name of the file, so add that method to the queue, not the file name itself. – AndreySarafanov Aug 29 '14 at 08:42
  • i am sorry but since i am new developer it's hard for me to understand what to do, can i have an example ? (ProcessFile(string file) method added but still same error) – maya remetz Aug 29 '14 at 08:45
  • @mayaremetz Ok. What exactly do you want to do with your files? Do you parse them or process in any other way? – AndreySarafanov Aug 29 '14 at 08:48
  • Check them via another class and then fired up event to my form (see my update) – maya remetz Aug 29 '14 at 08:55