问题
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;
}
回答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