Question about code in ManagedObjectCollection

Topics: CAB & Smart Client Software Factory
Oct 19, 2005 at 9:15 AM
originally posted by: DLorenz

What is the purpose of:

if (item is WorkItem)
throw new ArgumentException(Properties.Resources.ManagedObjectCollection_NoRemoveWorkItem, "item");

in this class? Why would you throw an exception when trying to remove a workitem from this collection, especially if it is Terminated? Instead, shouldn't it be:

if (item is WorkItem && ((WorkItem)item).Status != WorkItemStatus.Terminated) ?
throw new ArgumentException(Properties.Resources.ManagedObjectCollection_NoRemoveWorkItem, "item");

Thanks.
Oct 19, 2005 at 10:08 AM
originally posted by: BradWilsonMSFT

A terminated work item is automatically removed from its parent (at least, in the final release it will be; there's a bug here right now). That remove logic is handled elsewhere.

So, in theory, the only way you could call Remove would be with a live WorkItem. Since Remove says "I wish to take ownership of this object", it doesn't really fit for WorkItems, which must stay where they are in their hierarchy. So our guidance is that WorkItems must be terminated instead of removed.
Dec 20, 2005 at 7:27 AM
originally posted by: WalkingDisaster

Did this get fixed in the 11/14 release? I have code that subscribes to the Removed event of the WorkItems ManagedObjectCollection, and it never gets called. My concern is that without Remove (whether called automatically, or manually) long-running sessions can snowball in size.

I architected several single-use SmartParts, but if I can't be confident that they get cleaned up, I'll have to use a pool instead.
Dec 21, 2005 at 3:25 PM
originally posted by: BradWilsonMSFT

How do you define "fixed"? We fixed the fact that WorkItems weren't being properly removed when terminated.

If you mean that you want to be able to call Remove() on a WorkItem, no, that's not a bug. That's a purposeful limitation.
Dec 22, 2005 at 7:34 AM
originally posted by: WalkingDisaster

I would be satisfied if I didn't need to call Remove() to clean up my WorkItems, but what I'm witnessing is that terminating them isn't removing them either. I'm using the Dec release.

I accept that I'm probably doing something improperly, but I can't figure out where. I have stepped through the entire disposal of the WorkItem, and can't see where it is removed from the WorkItems collection. Where specifically is the WorkItem removed from its ManagedObjectCollection?
Dec 22, 2005 at 8:48 AM
originally posted by: BradWilsonMSFT

The ManagedObjectCollection is a view on top of the locator. It doesn't contain any actual items itself.

If you look inside of WorkItem.Dispose(bool), you can see a sizeable block of code that deals with removing references to the WorkItem from its parent's locator and lifetime container. In the December C# release, it's lines 721-736 in WorkItem.cs (starting with the line that says "if (parent != null)"). It enumerates through the entire parent locator looking for instances of itself, and caching off the IDs, so that it can later remove those IDs from the locator. Then it removes itself from the parent lifetime container. (The code about SmartPartInfos is something you can ignore for this discussion.)
Dec 28, 2005 at 6:54 AM
originally posted by: BradWilsonMSFT

I'm unable to reproduce this bug. The following test passes:

TestMethod
public void TerminatingWorkItems()
{
TestableRootWorkItem rwi = new TestableRootWorkItem();

Assert.AreEqual(0, rwi.WorkItems.Count);

WorkItem wi = rwi.WorkItems.AddNew<WorkItem>("Foo");

Assert.AreEqual(1, rwi.WorkItems.Count);
Assert.IsNotNull(rwi.WorkItems"Foo");

wi.Terminate();

Assert.AreEqual(0, rwi.WorkItems.Count);
Assert.IsNull(rwi.WorkItems"Foo");
}