This is a major upgrade for my multithreading library. If you are not familiar about what this library does, please read the other articles in this section.
New in this release are parallel operations: You can return ParallelOperation from within an asynchronous operation. The execution of the current operation will be suspended until all nested operations are executed. Additionally, a maximum number of parallel executions can be passed along, which allows you to further control the execution of the nested operations. And of course, you can select which exceptions you want to catch on each of the nested operation.
I'm primarily using these parallel operations in my InfiniTec.Exchange library to speed up lookups to Active Directory and the Exchange store. For example, when looking up members of a distribution list, I get a bunch of references, either to user in Active Directory, or references to contacts on an Exchange folder. Take a look at this method:
1 privateIEnumerable<OperationAction> RefreshInternal(AsyncOperation baseOperation)
2 {
3 Dictionary<NestedOperation,EntryIdReference> operations;
4 ExchangeStoreReference entryId;
5 List<IAddressListEntry> result;
6
7 _UnresolvableEntries = 0;
8
9 yieldreturnnewNestedOperation(baseOperation, false);
10
11
12 if (!_ResolveMembers)
13 {
14 _ResolveMembers = true;
15 yieldbreak;
16 }
17
18 entryId = newExchangeStoreReference(Properties.GetProperty<byte[]>(WellknownProperties.Item.EntryId).Value);
19
20 operations = newDictionary<NestedOperation, EntryIdReference>();
21
22 foreach (EntryIdReference reference in DecodeMembers(entryId.StoreId))
23 {
24 operations.Add(
25 newNestedOperation(reference.GetResolveOperation(BaseItem.Connection), false),
26 reference);
27 }
28
29 yieldreturnnewParallelOperations(operations.Keys, 5);
30
31 result = newList<IAddressListEntry>();
32
33 foreach (KeyValuePair<NestedOperation, EntryIdReference> entry in operations)
34 {
35 AsyncOperation<IAddressListEntry> operation;
36
37 operation = (AsyncOperation<IAddressListEntry>) entry.Key.Operation;
38 if (operation.StatusInformation != null)
39 {
40 result.Add(operation.StatusInformation);
41 }
42 else
43 {
44 _UnresolvableEntries++;
45 }
46 }
47
48 _Members = result.AsReadOnly();
49 }
In Line 9, I call the original refresh method, using the NestedOperation operation action. After that, I decode those member entries in lines 22 to 27 and put them in a dictionary. The interesting thing happens in line 29. At this point, I return a ParallelOperation operation action with a list of those member references. Additionally, a maximum number of concurrent operations of 5 is specified.
When the method resumes it's operation in line 31, all nested operations have been completed.