ASMX Web服务中线程的副作用

时间:2011-11-23 19:29:28

标签: c# multithreading sharepoint thread-safety asmx

我正在尝试为网站集中的所有网站运行SharePoint的SPSiteDataQuery以获取列表集合。从一个列表[spWeb.GetSiteData(dataQuery)]的所有站点获取数据的平均时间为1到20秒。列表集合中几乎可以包含任意数量的列表。

我已经实现了如下的线程逻辑。但是每次通话都会得到不同的记录。我对多线程架构的经验不多。发生了什么,是否值得我思考一个更好的线程架构?

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;
}

2 个答案:

答案 0 :(得分:1)

只是查看同步问题,您需要使用WaitAll()而不是循环WaitOne()或轮询IsAlive属性。 要进行设置,您需要为每个线程添加一个事件,然后将它们添加到主线程中的一个数组中,该数组将使用它来一次等待所有事件。 请注意,WaitAll()最多可以监视64个事件。

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

答案 1 :(得分:0)

对于整个服务,ASMX服务中的

static个字段(或者,就此而言,在任何服务中)都存在一次。这意味着如果你有两个请求同时进入,他们都在写同一组数据。