SharePoint "Thread was being aborted" looping through a SPListItemCollection
I have a SPListItemCollection with ~500 items in. I am looping through using a for each loop, each time grabbing the file and writing it out to a pdf document. I am getting the error "Thread was being aborted". It looks to be a time out issue but I dont know 开发者_开发技巧how to fix it? Collections with 200-300 items work fine. Is there any way I can stop getting this error. If I cant increase the timeout I will need to batch it up.
Update
I have tried splitting up the processing in batches of 100 items. With each new 100 items using a new spweb and site and pulling the items from sharepoint. This is all done within the same method (so I am not recreating my custom object) however the same error is still occuring...
http://blogs.msdn.com/solutions/archive/2009/01/08/getting-around-thread-was-being-aborted-error-when-creating-ep-site.aspx
In a basic text editor such as Notepad, open the web.config file for example '
%SYSTEMDRIVE%\Inetpub\wwwroot
-or-%SYSTEMDRIVE%\\Inetpub\wwwroot\wss\VirtualDirectories\80 folder
Press CTRL + F to open the Find dialog box.
Find the following tag:
<httpRuntime maxRequestLength="51200" />
Replace it with this tag:
<httpRuntime executionTimeout="6000" maxRequestLength="51200" />
This seems to have got it working for me.
Keep in mind there is a right and a very wrong way to iterate over list items, and it makes a huge difference in performance. The wrong way will cause n+1 calls to the database for the list data; the right way only makes a single call to the database.
Worst:
for (int i = 0; i < myList.Items.Count; i++)
{
SPListItem thisItem = myList.Items[i];
// yada yada yada
}
Bad:
foreach (SPListItem item in myList.Items)
{
// yada yada yada
}
Right:
SPListItemCollection myItems = myList.Items;
foreach (SPListItem item in myItems)
{
// yada yada yada
}
Updated: To reflect more accurate guidance
Iterating through an SPListItemCollection is never a good idea (but sadly sometimes the only way to go). You could consider wrapping up this code in a LongRunningOperation. Here's some code I adapted from some of my own:
ACTUAL CLASS:
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.SharePoint;
namespace Common.LongRunningJobs
{
/// <summary>
/// Provides a long running job wrapper around converting multiple files
/// </summary>
[CLSCompliant(false)]
public class FileToPdfLongRunningJob : LongRunningOperationJob
{
private List<string> fileUrls;
/// <summary>
/// Initializes a new instance of the <see cref="FileToPdfLongRunningJob"/> class.
/// </summary>
/// <param name="urls">The urls of the files to create pdfs from.</param>
public FileToPdfLongRunningJob(List<string> urls)
{
fileUrls = urls;
}
/// <summary>
/// Does the actual work of converting the files, while providing the user with status updates.
/// </summary>
public override void DoWork()
{
try
{
using (var currentWeb = Site.OpenWeb(parentWeb))
{
OperationsPerformed = 0;
foreach (var url in fileUrls)
{
SPFile file = currentWeb.GetFile(url);
// DO PDF OUTPUT
StatusDescription = string.Format(CultureInfo.InvariantCulture, "busy converting {0} van {1}, file: {2}...", (OperationsPerformed + 1), TotalOperationsToBePerformed, file.Name);
UpdateStatus();
OperationsPerformed++;
}
}
}
catch (Exception ex)
{
// LOG ERROR
}
}
}
}
USING ABOVE CLASS:
private void ConvertFiles()
{
const string PROGRESS_PAGE_URL = "/_layouts/LongRunningOperationProgress.aspx";
var urls = new List<string>();
foreach (SPListItem item in yourlistitemcollection)
{
urls.Add(item.File.Url);
}
var longRunningJob = new FileMoveLongRunningJob(urls)
{
Title = "Pdf conversion Long Running Job",
TotalOperationsToBePerformed = urls.Count,
RedirectWhenFinished = true,
NavigateWhenDoneUrl = urlToRedirectTo;//i.e. SPContext.GetContext(Context).List.RootFolder.ServerRelativeUrl
};
longRunningJob.Start(SPContext.Current.Web);
string url = string.Format("{0}{1}?JobId={2}", SPContext.Current.Web.Url, PROGRESS_PAGE_URL, longRunningJob.JobId);
SPUtility.Redirect(url, SPRedirectFlags.Default, Context);
}
Try creating new SPSite and SPWeb objects before getting items (and get them from new webs).
Often times that solves the problem.
There can be potential pit falls in the code that iterates list. It will be good if you can paste your code here. Also, its better to use Caml to query for list items and select only those fields that are required for your operation rather than all.
精彩评论