获取计算器异常并行每个,这是由于线程saftey? [英] Getting stackoverflow exception with Parallel for each , is this due to thread saftey?

查看:175
本文介绍了获取计算器异常并行每个,这是由于线程saftey?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个foreach循环效果很好。但我想要实现TPL,所以做了以下内容:

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

    如果(currentfileItem.File == NULL)
    {
        抛出新的异常(
            的String.Format(文件信息未找到该项目{0},
                currentfileItem.DisplayName));
    }

    VAR currentFileName = currentfileItem.File.Name;



    如果(!string.IsNullOrEmpty(docRevVersionId))
    {
        VAR信息= Microsoft.SharePoint.Client.File.OpenBinaryDirect(
            _clientContext,currentfileItem [FREF]的ToString())。
        如果(资讯!= NULL)
        {
            UpdateToServer(同上,currentFileName,info.Stream);
        }
    }


});
 

在我实现TPL我越来越计算器异常。我是pretty的肯定,这是因为第三方物流,因为没有第三方物流的应用程序运行正常。

的fileList 的IEnumerable<列表项>

编辑:

的国有企业可能是这样的:(VS已经跑出来的内存来存储的除外)

和更新code:

  Parallel.ForEach(的fileList,
                  ()=> CreateClientContext(ConfigurationDetails.SharePointUri),//这个函数会为指定的URL一个新的环境。
                  (currentfileItem,loopState,localContext)=>
                  {


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

                    如果(currentfileItem.File == NULL)
                    {
                        抛出新的异常(的String.Format(找不到文件的项目{0}的信息,currentfileItem.DisplayName));
                    }

                    VAR currentFileName = currentfileItem.File.Name;



                    如果(!string.IsNullOrEmpty(docRevVersionId))
                    {
                        VAR信息= Microsoft.SharePoint.Client.File.OpenBinaryDirect(_clientContext,currentfileItem [FREF]的ToString());
                        如果(资讯!= NULL)
                        {
                            UpdateToServer(同上,currentFileName,info.Stream);
                        }
                    }


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

 私有静态ClientContext CreateClientContext(字符串URI)
        {
            ClientContext上下文=新的ClientContext(URI);

            //...魔法...

            返回范围内;
        }
 

解决方案

<一个href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.clientcontext%28v=office.14%29.aspx"相对=nofollow> ClientContext 不是线程安全的,所以你需要有它的每个线程一个实例。 Parallel.ForEach 已建成为使本地线程对象的方法,所以你不需要创建它每次循环,只是每一个线程产卵。

  Parallel.ForEach(的fileList,
                 ()=&GT; CreateClientContext(storeUrl),//这个函数会为指定的URL一个新的环境。
                 (currentfileItem,loopState,localContext)=&GT;
{
    localContext.Load(currentfileItem,瓦特=&GT; w.File);
    localContext.ExecuteQuery();

    如果(currentfileItem.File == NULL)
    {
        抛出新的异常(
            的String.Format(文件信息未找到该项目{0},
                currentfileItem.DisplayName));
    }

    VAR currentFileName = currentfileItem.File.Name;



    如果(!string.IsNullOrEmpty(docRevVersionId))
    {
        VAR信息= Microsoft.SharePoint.Client.File.OpenBinaryDirect(
            localContext,currentfileItem [FREF]的ToString())。
        如果(资讯!= NULL)
        {
            UpdateToServer(同上,currentFileName,info.Stream);
        }
    }

    返回localContext;
},
              (localContext)=&GT; localContext.Dispose()); //处置线程局部范围内


//别处
私有静态ClientContext CreateClientContext(字符串URL)
{
    ClientContext上下文=新的ClientContext(URL);

    //执行你的情况下在这里需要任何额外的设置。
    //如果你不需要任何你可以只更换CreateClientContext(storeUrl)
    //以新ClientContext(storeUrl)起来,在给ForEach声明。

    返回范围内;
}
 

您可能希望寻找到 UpdateToServer 并检查它也是线程安全的。

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)

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

解决方案

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.

这篇关于获取计算器异常并行每个,这是由于线程saftey?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆