简体   繁体   English

System.Linq.Enumerable出错。 <TakeIterator> d__3a`1.MoveNext()

[英]Error on System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()

I have the following code to iterate over subwebs of a sharepoint site. 我有以下代码来迭代sharepoint站点的子站点。 If I debug it line by line, it never goes to my catchs. 如果我逐行调试它,它永远不会被我的捕获。

however on the uls logs I have this exception which I dont know what it means or if I should worry 但是在uls日志中,我有这个例外,我不知道这意味着什么,或者我应该担心

53b416d1-1497-4b40-beb5-cd261180ece8 Stack trace:   
 at Microsoft.SharePoint.SPWeb.get_Created()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>b__7(SPWeb d)    
 at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)    
 at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)    
 at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()    
 at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>b__5()    
 at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass5.<RunWithElevatedPrivileges>b__3()    
 at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)    
 at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)    
 at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.LoadGridData()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.OnPreRender(EventArgs e)    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)    
 at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)    
 at System.Web.UI.Page.ProcessRequest()    
 at System.Web.UI.Page.ProcessRequest(HttpContext context)    
 at Microsoft.SharePoint.Publishing.TemplateRedirectionPage.ProcessRequest(HttpContext context)    
 at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()    
 at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)    
 at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)    
 at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)    
 at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)    
 at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

My code is as follows 我的代码如下

private void LoadGridData()
        {
            try
            {
                String currentUrl = SPContext.Current.Site.Url;

                var jobInfoList = new List<JobInfo>();

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (var clientSiteCollection = new SPSite(currentUrl))
                    {
                        foreach (
                            SPWeb web in
                                clientSiteCollection.AllWebs.AsSafeEnumerable().Where(
                                    c =>
                                    c.AllProperties[Constants.WebProperties.General.WebTemplate] != null &&
                                    c.AllProperties[Constants.WebProperties.General.WebTemplate].ToString() ==
                                    Constants.WebTemplates.JobWebPropertyName).OrderByDescending(d => d.Created).Take(5)
                            )
                        {
                            if (web.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName,
                                SPBasePermissions.Open))
                            {
                                SPList jobInfoListSp = web.Lists.TryGetList(Constants.Lists.JobInfoName);
                                if (jobInfoListSp != null)
                                {
                                    if (jobInfoListSp.Items.Count > 0)
                                    {
                                        var value =
                                            new SPFieldUrlValue(
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.iPowerLink].ToString());

                                        jobInfoList.Add(new JobInfo
                                        {
                                            JobName =
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobName].ToString(),
                                            JobCode =
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobCode].ToString(),
                                            IPowerLink = value.Url,
                                            JobWebsite = web.Url,
                                            IsConfidential =
                                                HelperFunctions.ConvertToBoolean(
                                                    jobInfoListSp.Items[0][Constants.FieldNames.Job.Confidential]
                                                        .ToString())
                                        });
                                    }
                                }
                            }

                            web.Dispose();
                        }
                    }
                });

                _lastCreatedJobsGrid.DataSource = jobInfoList;
                _lastCreatedJobsGrid.DataBind();
            }
            catch (Exception ex)
            {
                LoggingService.LogError(LoggingCategory.Job, ex);
            }
        }



 public static class SPWebCollectionExtensions
    {
        public static IEnumerable<SPWeb> AsSafeEnumerable(this SPWebCollection webs)
        {
            foreach (SPWeb web in webs)
            {
                try
                {
                    yield return web;
                }
                finally
                {
                    web.Dispose();
                }
            }
        }
    }

Any idea what could be the cause and solution if needed? 如果需要,任何想法可能是什么原因和解决方案?

Update: 更新:

I made the query on a variable first, and then the foreach, I also removed the AsSafeEnumerable I wonder if I will have memoryleaks with this change? 我首先对变量进行了查询,然后是foreach,我还删除了AsSafeEnumerable,我想知道我是否会对此更改进行内存泄漏?

Update 2: When trying to use the code in the first answer which is impressive, I still get disposing problems. 更新2:当尝试在第一个答案中使用令人印象深刻的代码时,我仍然处理问题。

An 一个

SPRequest object was not disposed before the end of this thread.  To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it.  This object will now be disposed.  Allocation Id: {96F3F1CB-DBD1-4514-AB9A-D49424AB0B6A}  This SPRequest was allocated
 at   
 at Microsoft.SharePoint.Library.SPRequest..ctor()    
 at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[] UserToken, SPAppPrincipalToken appPrincipalToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous)    
 at Microsoft.SharePoint.SPWeb.InitializeSPRequest()    
 at Microsoft.SharePoint.SPWeb.EnsureSPRequest()    
 at Microsoft.SharePoint.SPWeb.get_AllProperties()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>b__6(SPWeb c)    
 at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()    
 at System.Linq.Buffer`1..ctor(IEnumerable`1 source)    
 at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()    
 at xx.SP.DMS.WebParts.Extensions.Safe.<SafeTake>d__0`1.MoveNext()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>b__5()    
 at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass5.<RunWithElevatedPrivileges>b__3()    
 at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)    
 at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)    
 at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.LoadGridData()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.OnPreRender(EventArgs e)    

I believe the problem is the SPWeb is getting disposed after invoking the Enumerable.OrderByDescending . 我相信问题是在调用Enumerable.OrderByDescendingSPWeb正在被处理掉。 This linq method is not lazy evaluated, so the finally block inside AsSafeEnumerable will get triggered. 这个linq方法不是惰性求值,因此AsSafeEnumerablefinally块将被触发。

Sample: 样品:

public class Disposed : IDisposable
{
    public bool IsDisposed { get; private set; }
    public DateTime? Created { get; set; }

    public void Dispose()
    {
        Console.WriteLine("Disposed");
        IsDisposed = true;
    }
}

public IEnumerable<Disposed> GetDisposed()
{
    Func<Disposed> factory = () => new Disposed { Created = DateTime.Now };
    foreach(var f in Enumerable.Repeat(factory, 5))
    {
        Console.WriteLine("In Enumerable");
        var item = f();
        try
        {
            Console.WriteLine("Returning item");
            yield return item;
        }
        finally
        {
            item.Dispose();
        }

        Console.WriteLine("Next iteration.");
    }
}

Usage 1: 用法1:

foreach(var item in GetDisposed().Take(5))
{
    Console.WriteLine(item.IsDisposed);
}

In Enumerable
Returning item
False
Disposed
Next iteration.
In Enumerable
Returning item
False
Disposed
Next iteration.
In Enumerable
Returning item
False
Disposed
Next iteration.
In Enumerable
Returning item
False
Disposed
Next iteration.
In Enumerable
Returning item
False
Disposed

Usage 2: 用法2:

foreach(var item in GetDisposed().OrderByDescending(x => x.Created).Take(5))
{
    Console.WriteLine(item.IsDisposed);
}

Log: 日志:

In Enumerable
Returning item
Disposed
Next iteration.
In Enumerable
Returning item
Disposed
Next iteration.
In Enumerable
Returning item
Disposed
Next iteration.
In Enumerable
Returning item
Disposed
Next iteration.
In Enumerable
Returning item
Disposed
Next iteration.
True
True
True
True
True

Edit: 编辑:

Here is an extension method to safely dispose objects not taken: 这是一种安全地处理未采取的对象的扩展方法:

public static IEnumerable<TSource> SafeTake<TSource>(
    this IEnumerable<TSource> source,
    int count
) where TSource : IDisposable
{
    foreach(var item in source)
    {
        if(--count >= 0)
        {
            yield return item;
        }
        else if (item != null)
        {
            item.Dispose();
        }
    }
}

public static IEnumerable<TSource> SafeWhere<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
) where TSource: IDisposable
{
    return source.SelectMany(x => {
        var result = predicate(x);
        if(!result && x != null) x.Dispose();
        return Enumerable.Repeat(x, result ? 1 : 0);
    });
}

Usage: 用法:

foreach (
    SPWeb web in
        clientSiteCollection.AllWebs.SafeWhere(
            c =>
            c.AllProperties[Constants.WebProperties.General.WebTemplate] != null &&
            c.AllProperties[Constants.WebProperties.General.WebTemplate].ToString() ==
            Constants.WebTemplates.JobWebPropertyName).OrderByDescending(d => d.Created).SafeTake(5)
    )
{
    try
    {
        if (!web.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName, SPBasePermissions.Open)) continue;
        SPList jobInfoListSp = web.Lists.TryGetList(Constants.Lists.JobInfoName);
        if (jobInfoListSp == null) continue;
        if (0 >= jobInfoListSp.Items.Count) continue;

        var value =
            new SPFieldUrlValue(
                jobInfoListSp.Items[0][Constants.FieldNames.Job.iPowerLink].ToString());

        jobInfoList.Add(new JobInfo
        {
            JobName =
                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobName].ToString(),
            JobCode =
                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobCode].ToString(),
            IPowerLink = value.Url,
            JobWebsite = web.Url,
            IsConfidential =
                HelperFunctions.ConvertToBoolean(
                    jobInfoListSp.Items[0][Constants.FieldNames.Job.Confidential]
                        .ToString())
        });
    }
    finally
    {
        web.Dispose();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法投射 <TakeIterator> d__3a`1 [System.Object]键入System.Collections.Generic.IEnumerable - Unable cast <TakeIterator>d__3a`1[System.Object] to type System.Collections.Generic.IEnumerable LINQ foreach循环中的System.Linq.Enumerable + d__3a`1 [System.String]错误 - System.Linq.Enumerable+d__3a`1[System.String] error in LINQ foreach loop 方法系统linq的类型参数可枚举为可枚举-错误 - the type arguments for method system linq enumerable as enumerable - Error System.Linq.Enumerable + WhereSelectListIterator`2 - System.Linq.Enumerable+WhereSelectListIterator`2 出现错误-&gt; System.Linq.Enumerable + WhereSelectListIterator`2 [Tdsb.Aris.Pims.Entity.PartnershipFunding,System.String] - Getting error -> System.Linq.Enumerable+WhereSelectListIterator`2[Tdsb.Aris.Pims.Entity.PartnershipFunding,System.String] 将对象转换为System.Linq.Enumerable - Casting object to System.Linq.Enumerable 查询后更新System.Linq.Enumerable - Updating a System.Linq.Enumerable after the query C# 调用反向时出错:System.Linq.Enumerable+ReverseIterator`1[System.Char] - C# Error when calling Reverse : System.Linq.Enumerable+ReverseIterator`1[System.Char] 为什么System.Linq.Enumerable中没有SelectToArray方法 - Why there is no SelectToArray method in System.Linq.Enumerable 使用反射调用OrderBy(System.Linq.Enumerable) - Invoking OrderBy (System.Linq.Enumerable) with Reflection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM