Getting stackoverflow exception with Parallel for each , is this due to thread saftey?

孤街醉人 提交于 2021-02-10 07:51:39

问题


I have a foreach loop which works Well . But I want to implement TPL , so did the following:

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


});

Once I implement TPL I am getting StackOverflow Exception . I am pretty sure this is because of TPL because without TPL the application runs fine.

fileList is IEnumerable<ListItem>

Edit:

The SOE probably for this: (VS has ran out of memory to store the exception) enter image description here

and updated code:

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

回答1:


ClientContext is not thread safe, so you need to have one instance of it per thread. Parallel.ForEach has built in methods for making thread local objects, so you don't need to create it every loop iteration, just every thread spawning.

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

You may want to look in to UpdateToServer and check that it also is thread safe.



来源:https://stackoverflow.com/questions/19981744/getting-stackoverflow-exception-with-parallel-for-each-is-this-due-to-thread-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!