Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm trying out multithreading with the SP2010 Object Model and I've run into some weirdness.

My application currently does the following:

  1. Opens an SPSite and uses AllWebs.WebsInfo to build a Guid[] of the IDs of all the webs in the site.
  2. Creates e.g. 10 threads. Each thread:
    1. Opens the same SPSite
    2. Gets the next web ID in a thread-safe manner that's not causing any trouble.
    3. Opens that SPWeb.
    4. Gets a particular list from it.
    5. Tries to iterate through the items.
    6. When done, gets the next ID, or finishes if there are none left.

At step 2.5., all of my threads hang. It's at the point where they're causing EnsureListItemsData to be called ten times near-simultaneously, on separate lists, and it seems to break.

However, if between steps 1. and 2. I cause EnsureListItemsData to be called, for example by calling site.RootWeb.Lists["MyList"].Items.Count, everything is fine. The problem only arises when the ten simultaneous calls are the first calls to EnsureListItemsData in the process.

Can anyone tell me why this is happening? I don't understand why it's locking up, and thus don't trust my "fix" to be reliable.

Here's a shortened program that exhibits the same problem. The threads just call Items.Count rather than trying to iterate. The line that causes the problem to go away is commented out.

class Program {
    static Guid[] webIDs;
    static int currentIndex;

    static Guid? NextWebID { 
        get {
            int index = Interlocked.Increment(ref currentIndex);
            if (index < webIDs.Length) return webIDs[index];
            return null;
        }
    }

    static void Main(string[] args) {
        currentIndex = -1;
        using (var site = new SPSite("http://portal")) {
            webIDs = site.AllWebs.WebsInfo.Select(wi => wi.Id).ToArray();
            //var i = site.RootWeb.Lists["Pages"].Items.Count;
        }

        var threads = Enumerable.Range(1, 10).Select(i => new Thread(Work)).ToArray();
        threads.All(t => { t.Start(); return true; });
        threads.All(t => { t.Join(); return true; });
    }

    static void Work() {
        using (var site = new SPSite("http://portal")) {
            Guid? webID = null;
            while ((webID = NextWebID).HasValue) {
                using (var web = site.OpenWeb(webID.Value)) {
                    var i = web.Lists["Pages"].Items.Count;
                }
            }
        }
    }
}
share|improve this question
    
I am theorising but EnsureListsData is making sure the list is in the current context, you are running on a separate thread, so I presume it doesn't have context access until this is run? –  Hugh Wood Nov 16 '12 at 12:59
    
I'm not sure I follow - what do you mean by the current context? This is just a console app so SPContext.Current is null throughout. –  Rawling Nov 16 '12 at 13:20
    
Well in this case it would be making sure that the thread is running in the context of the SPWeb you are supplying, it's the only part of EnsureListItemsData that seems to do anything that would affect the process. –  Hugh Wood Nov 16 '12 at 13:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.