2

我有一个运行良好的 foreach 循环。但我想实现 TPL ,所以做了以下:

Parallel.ForEach(fileList, currentfileItem =>
{
    _clientContext.Load(currentfileItem, w => w.File);
    _clientContext.ExecuteQuery();

    if (currentfileItem.File == null)
    {
        throw new Exception(
            String.Format("File information not found for the item {0}",
                currentfileItem.DisplayName));
    }

    var currentFileName = currentfileItem.File.Name;



    if (!string.IsNullOrEmpty(docRevVersionId))
    {
        var info = Microsoft.SharePoint.Client.File.OpenBinaryDirect(
            _clientContext, currentfileItem["fRef"].ToString());
        if (info != null)
        {
            UpdateToServer(Id, currentFileName, info.Stream);
        }
    }


});

一旦我实施 TPL,我就会得到StackOverflow Exception. 我很确定这是因为 TPL,因为没有 TPL,应用程序运行良好。

fileListIEnumerable<ListItem>

编辑:

SOE 可能是为了这个:(VS 已用尽内存来存储异常) 在此处输入图像描述

和更新的代码:

Parallel.ForEach(fileList,
                  () => CreateClientContext(ConfigurationDetails.SharePointUri), //This function creates a new context for the specified url. 
                  (currentfileItem, loopState, localContext) =>
                  {


                    _clientContext.Load(currentfileItem, w => w.File);
                    _clientContext.ExecuteQuery();

                    if (currentfileItem.File == null)
                    {
                        throw new Exception(String.Format("File information not found for the item {0}", currentfileItem.DisplayName));
                    }

                    var currentFileName = currentfileItem.File.Name;



                    if (!string.IsNullOrEmpty(docRevVersionId))
                    {
                        var info = Microsoft.SharePoint.Client.File.OpenBinaryDirect(_clientContext, currentfileItem["fRef"].ToString());
                        if (info != null)
                        {
                            UpdateToServer(Id, currentFileName, info.Stream);
                        }
                    }


                },localContext => localContext.Dispose());

 private static ClientContext CreateClientContext(string URI)
        {
            ClientContext context = new ClientContext(URI);

            //...Magic...

            return context;
        }
4

1 回答 1

4

ClientContext不是线程安全的,因此每个线程都需要一个实例。Parallel.ForEach内置了用于制作线程本地对象的方法,因此您无需在每次循环迭代时创建它,只需在每个线程产生时创建它。

Parallel.ForEach(fileList, 
                 () => CreateClientContext(storeUrl), //This function creates a new context for the specified url. 
                 (currentfileItem, loopState, localContext) =>
{
    localContext.Load(currentfileItem, w => w.File);
    localContext.ExecuteQuery();

    if (currentfileItem.File == null)
    {
        throw new Exception(
            String.Format("File information not found for the item {0}",
                currentfileItem.DisplayName));
    }

    var currentFileName = currentfileItem.File.Name;



    if (!string.IsNullOrEmpty(docRevVersionId))
    {
        var info = Microsoft.SharePoint.Client.File.OpenBinaryDirect(
            localContext, currentfileItem["fRef"].ToString());
        if (info != null)
        {
            UpdateToServer(Id, currentFileName, info.Stream);
        }
    }

    return localContext;
},
              (localContext) => localContext.Dispose()); //Dispose the thread local context


//Elsewhere
private static ClientContext CreateClientContext(string url)
{
    ClientContext context = new ClientContext(url);

    //Perform any additional setup you need on the context here.
    //If you don't need any you could just replace "CreateClientContext(storeUrl)"
    //with "new ClientContext(storeUrl)" up at the ForEach declaration.

    return context;
}

您可能需要查看UpdateToServer并检查它是否也是线程安全的。

于 2013-11-14T16:05:30.867 回答