Iterator Handler Questions

Oct 29, 2010 at 11:25 AM

Hi Guys,

This is what I'm trying to do.

1) Create Iterator Handler to handle multiple Process A

2) Process A also has a sub process (Lets call it Process B) which can be multi threaded HOWEVER, the results of Process B need to be zipped up and this call is not thread safe

This is very similar to the IteratorHandler example in the Usage Scenarios however I have a few questions on this.

A) If I declare my ZIP class in Process A, run my foreach to call Process B, after the yield, does processing continue on the same Process A thread and therefore the code will work e.g.

[XcoConcurrent]
IEnumerator<ITask> ProcessA(string msg) 
{
			MyZipLibrary myZip = new MyZipLibrary();
			foreach (var data in AllData)
{
ProcessB.Post(new ProcessBProc {Var = Data, ResponsePort = responsePort});

yield return responsePort.Receive();

result = responsePort;
				myZip.Add(result); - IS THIS OK if myZip is not thread safe? i.e Will this call run on the same thread the whole time
}

If not, can you suggest a way to do this?

B) Is there a reason you pass in the second worker as opposed to creating it in the ProcessA worker? i.e. In your example you have

var w = space.RunWorker(new TextCalculationWorker(space.RunWorker(new MathWorker())));

Could you also not create it within Process A. Just wanted to make sure I'm not missing something.

C) Just for my own clarity, in the example here, if you did not have the second worker and just called something like Add.AddNumbers(Num1, Num2) in the foreach iterator, the yield would hand control back to the CCR but the foreach loop would not continue until the  AddNumbers method completed - Is that correct?

 

Many thanks in advance for your help

Mike

Coordinator
Nov 3, 2010 at 9:36 AM
Edited Nov 3, 2010 at 9:39 AM

Hi Mike,

A) Yes, this should work without a problem. Since the code in your ProcessA method is actually sequential, there will never be any concurrent calls to myZip.Add(), therefore the method doesn't need to be Threadsafe.

B) It would of course also be possible to create one worker directly within the other, but there are some reasons why the given solution is probably better: This way the TextCalculationWorker is not dependent on a certain implementation of MathWorker, any object implementing the MathWorker Contract could be handed in, e.g. a Mock, which makes it easily testable. Also, to create the MathWorker, the TextCalculationWorker would need to know the space instance, which would make testing the TextCalculationWorker in an isolated scenario even more difficult.

C) I'm not sure if I understand your question. If you would just be calling a method instead of posting something and then yielding to a port, you wouldn't need to use the yield statement any more, in which case it would then be a normal loop and the control would not be handed back to the ccr until the method is finished. If your question is whether you can have nested method calls that are using yield, yes that is possible, but in this case you need to call your inner method in a foreach loop:

IEnumerator<ITask> Method1(string msg) 
{
   ...
   foreach (var task in Method2(msg))
      yield return task;
   ...
}

IEnumerable<ITask> Method2(string msg)
{
   ... doSomething with yield...
}

Hope I could help you!

Thomas