2011-11-23 61 views
0

我正在嘗試爲網站集中的所有網絡運行SharePoint的SPSiteDataQuery以獲取列表集合。從一個列表[spWeb.GetSiteData(dataQuery)]的所有站點獲取數據的平均時間爲1到20秒之間的任意值。列表集合實際上可以包含任意數量的列表。線程在ASMX Web服務中的副作用

我已經實現瞭如下的線程邏輯。但是,我在每次通話中獲得不同數量的記錄。我對多線程體系結構並不熟悉。發生了什麼事情,值得我思考一個更好的線程架構嗎?

private static Dictionary<string,string> _workTypes = new Dictionary<string, string>(); 
private static Dictionary<string,string> _workspaces = new Dictionary<string, string>(); 
private static List<string> _processedMyWorkItems = new List<string>(); 
private static readonly object Locker = new object(); 

var threads = new List<Thread>(); 
var processedMyWorkData = new Dictionary<string, List<XElement>>(); 

foreach (string selectedList in selectedLists.Distinct().OrderBy(l => l)) 
{ 
    string theSelectedList = selectedList; 

    string listIds = string.Empty; 

    foreach (string listId in GetListIdsFromDb(selectedList, spWeb, archivedWebs) 
     .Where(listId => !selectedListIds.Contains(listId))) 
    { 
     selectedListIds.Add(listId); 
     listIds += string.Format(@"<List ID='{0}'/>", listId); 
    } 

    if (string.IsNullOrEmpty(listIds)) continue; 

    dataQuery.Lists = string.Format("<Lists MaxListLimit='0'>{0}</Lists>", listIds); 

    var thread = new Thread(() => 
    { 
     List<XElement> processedMyWork = ProcessMyWork(selectedFields, spSite, spWeb, dataQuery, fieldTypes); 

     lock (Locker) 
     { 
      processedMyWorkData.Add(theSelectedList, processedMyWork); 
     } 
    }) { Name = theSelectedList }; 

    threads.Add(thread); 
    thread.Start(); 
} 

bool done = false; 

while (!done) 
{ 
    Thread.Sleep(500); 

    bool noThreadIsAlive = true; 
    var threadsCompleted = new List<Thread>(); 

    foreach (var thread in threads) 
    { 
     if (thread.IsAlive) 
     { 
      noThreadIsAlive = false; 
     } 
     else 
     { 
      threadsCompleted.Add(thread); 
     } 
    } 

    foreach (var thread in threadsCompleted) 
    { 
     threads.Remove(thread); 

     string key = thread.Name; 
     foreach (var xElement in processedMyWorkData[key]) 
     { 
      result.Element("MyWork").Add(xElement); 
     } 

     lock (Locker) 
     { 
      processedMyWorkData.Remove(key); 
     } 
    } 

    done = noThreadIsAlive; 
} 
+0

的TPL(任務並行庫)使這樣的工作更容易(或至少更容易閱讀)比手動使用線程。 –

+0

你在什麼版本的.NET?似乎你可以從使用.NET 4.0中的任務中獲益 –

+0

@JamesMichaelHare:我同意。但是,SharePoint無法處理.Net 4.0,但! – Moon

回答

1

只看同步問題,您需要使用WaitAll()而不是圍繞WaitOne()循環或輪詢IsAlive屬性。 要設置它,您需要爲每個線程添加一個事件,然後將它們添加到主線程中的數組中,以便使用它來一次等待所有事件。 請注意,最多可以由WaitAll()監視的64個事件。

http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx

0

static在ASMX服務(或,對於這個問題,在任何服務)字段爲整個服務存在一次。這意味着如果你有兩個請求同時進入,它們都在寫同一組數據。

+0

好的,那麼你會推薦什麼作爲更好的方法? – Moon

+1

我會首先嚐試沒有靜態和沒有多線程的。爲確保性能或可擴展性,請確保您需要它。如果您可以提供幫助,您不想使用這項傳統技術進行線程處理。這並不意味着打得很好,至少不容易。 –

+0

嗯,這是在生產代碼工作很好,只有幾個名單和網站。但是對於集合中的每個附加列表和網站,性能都會降低。 – Moon