每个都有并行的堆栈溢出异常,这是由于线程安全吗?

时间:2013-11-14 15:32:08

标签: c# .net c#-4.0 task-parallel-library

我有一个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内存不足以存储异常) enter image description here

并更新了代码:

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 个答案:

答案 0 :(得分: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并检查它是否也是线程安全的。