2011-11-23 3 views
0

목록 모음의 사이트 모음에있는 모든 웹에 대해 SharePoint의 SPSiteDataQuery을 실행하려고합니다. 하나의 목록 [spWeb.GetSiteData(dataQuery)]에 대한 모든 사이트의 데이터를 가져 오는 평균 시간은 1 ~ 20 초 사이입니다. 리스트 콜렉션은 사실상 그 안에리스트를 가질 수 있습니다.ASMX 웹 서비스에서 스레딩의 부작용

다음과 같이 스레딩 논리를 구현했습니다. 그러나 나는 모든 부름마다 서로 다른 양의 기록을 얻습니다. 멀티 스레딩 아키텍처에 익숙하지 않습니다. 무슨 일이 벌어지고 있으며, 더 나은 스레딩 아키텍처에 대한 내 생각에 가치가 있습니까?

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(); 
(어떤 서비스 또는 그 문제에 대해,,)는 ASMX 서비스의
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에서 Tasks를 사용하면 도움이 될 것 같습니다. –

+0

@JamesMichaelHare : 동의합니다. 하지만 SharePoint는 .Net 4.0을 처리 할 수 ​​없습니다. – Moon

답변

1

동기화 문제 만보고 WaitOne()을 반복하거나 IsAlive 속성을 폴링하지 말고 WaitAll()을 사용해야합니다. 설정하려면 각 스레드에 대한 이벤트가 필요하며이를 주 스레드의 배열에 추가하십시오.이 스레드를 사용하여 모든 이벤트를 한 번에 대기합니다. WaitAll()로 모니터링 할 수있는 이벤트는 최대 64 개입니다.

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

0

static 필드는 전체 서비스 한번 존재한다. 즉, 동시에 두 가지 요청이 들어 오면 둘 다 같은 데이터 집합을 쓰고 있습니다.

+0

그래, 그럼 더 나은 접근 방법으로 무엇을 권하고 싶습니까? – Moon

+1

나는 statics없이 multithreading없이 이것을 시도 할 것이다. 성능 또는 확장 성을 위해 필요하다고 절대적으로 확신하십시오. 도움이 될 수 있다면이 레거시 기술로 스레딩 작업을하고 싶지 않을 것입니다. 적어도 실제로는 훌륭하게 연주하는 것이 아닙니다. –

+0

글쎄요, 이것은 프로덕션 코드에서 단지 몇 가지 목록과 사이트로 잘 작동했습니다. 그러나 컬렉션의 각 추가 목록 및 사이트에 대한 성능은 실제로 저하됩니다. – Moon

관련 문제