1

我最近開始使用新的Outlook/Office 365的REST API,並得到有關authentication(新V2.0應用程序模型)一些很大的幫助,scopes,使用OutlookServicesClient並寫出更好(linq-)queriesSystemOutOfMemoryException同時使用OutlookServicesClient

不幸的是,一些用戶報告了一些內存的問題,這就造成了以下System.OutOfMemoryException

Exception of type 'System.OutOfMemoryException' was thrown. : at Microsoft.OData.Core.Json.JsonReader.ReadInput() 
     at Microsoft.OData.Core.Json.JsonReader.ParseStringPrimitiveValue(Boolean& hasLeadingBackslash) 
     at Microsoft.OData.Core.Json.JsonReader.ParseValue() 
     at Microsoft.OData.Core.Json.JsonReader.Read() 
     at Microsoft.OData.Core.Json.BufferingJsonReader.ReadInternal() 
     at Microsoft.OData.Core.Json.BufferingJsonReader.ReadNextAndCheckForInStreamError() 
     at Microsoft.OData.Core.Json.BufferingJsonReader.ReadInternal() 
     at Microsoft.OData.Core.Json.BufferingJsonReader.Read() 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightDeserializer.ParseProperty(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, Func`2 readPropertyAnnotationValue, String& parsedPropertyName) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightDeserializer.ProcessProperty(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, Func`2 readPropertyAnnotationValue, Action`2 handleProperty) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightPropertyAndValueDeserializer.ReadComplexValue(IEdmComplexTypeReference complexValueTypeReference, String payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightPropertyAndValueDeserializer.ReadNonEntityValueImplementation(String payloadTypeName, IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, Boolean validateNullValue, Boolean isTopLevelPropertyValue, Boolean insideComplexValue, String propertyName, Nullable`1 isDynamicProperty) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightEntryAndFeedDeserializer.ReadEntryDataProperty(IODataJsonLightReaderEntryState entryState, IEdmProperty edmProperty, String propertyTypeName) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightEntryAndFeedDeserializer.ReadEntryPropertyWithValue(IODataJsonLightReaderEntryState entryState, String propertyName) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightEntryAndFeedDeserializer.<>c__DisplayClass2.<ReadEntryContent>b__0(PropertyParsingResult propertyParsingResult, String propertyName) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightDeserializer.ProcessProperty(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, Func`2 readPropertyAnnotationValue, Action`2 handleProperty) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightEntryAndFeedDeserializer.ReadEntryContent(IODataJsonLightReaderEntryState entryState) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightReader.ReadEntryStart(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, SelectedPropertiesNode selectedProperties) 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightReader.ReadAtEntryEndImplementationSynchronously() 
     at Microsoft.OData.Core.JsonLight.ODataJsonLightReader.ReadAtEntryEndImplementation() 
     at Microsoft.OData.Core.ODataReaderCore.ReadImplementation() 
     at Microsoft.OData.Core.ODataReaderCore.ReadSynchronously() 
     at Microsoft.OData.Core.ODataReaderCore.InterceptException[T](Func`1 action) 
     at Microsoft.OData.Core.ODataReaderCore.Read() 
     at Microsoft.OData.Client.Materialization.ODataReaderWrapper.Read() 
     at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.TryRead() 
     at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.TryStartReadFeedOrEntry() 
     at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadEntry(MaterializerEntry& entry) 
     at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.<LazyReadEntries>d__0.MoveNext() 
     at Microsoft.OData.Client.Materialization.FeedAndEntryMaterializerAdapter.Read() 
     at Microsoft.OData.Client.Materialization.ODataReaderEntityMaterializer.ReadNextFeedOrEntry() 
     at Microsoft.OData.Client.Materialization.ODataEntityMaterializer.ReadImplementation() 
     at Microsoft.OData.Client.MaterializeAtom.MoveNextInternal() 
     at Microsoft.OData.Client.MaterializeAtom.MoveNext() 
     at System.Linq.Enumerable.<CastIterator>d__94`1.MoveNext() 
     at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
     at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
     at Microsoft.OData.ProxyExtensions.PagedCollection`2..ctor(DataServiceContextWrapper context, QueryOperationResponse`1 qor) 
     at Microsoft.OData.ProxyExtensions.DataServiceContextWrapper.<>c__DisplayClass38`2.<ExecuteAsync>b__36(IAsyncResult r) 
     at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization) 
    --- End of stack trace from previous location where exception was thrown --- 
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
     at Microsoft.OData.ProxyExtensions.DataServiceContextWrapper.<ExecuteAsync>d__3a`2.MoveNext() 
    --- End of stack trace from previous location where exception was thrown --- 
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) 
     at Shared.Data.Office365.Office365Api.<GetEmailsReceived>d__23.MoveNext() 

我的查詢(得到的日期收到的電子郵件的數量)是這樣的:

var dtStart = date.Date.ToUniversalTime(); 
var dtEnd = date.Date.AddDays(1).ToUniversalTime(); 

var mailResults = await _client.Me.Messages 
    .OrderByDescending(m => m.ReceivedDateTime) 
    .Where(m => m.ReceivedDateTime.Value >= dtStart && m.ReceivedDateTime.Value <= dtEnd) 
    //todo: filter if not in Junk Email and Deleted Folder (maybe with ParentFolderId) 
    .Take(500) // todo: add paging to (and maybe make more efficient?) 
    .Select(m => new DisplayEmail(m)).ExecuteAsync(); 

// todo: add paging to (and maybe make more efficient?) 
foreach (var message in mailResults.CurrentPage) 
{ 
    emails.Add(message); 
} 

我沒有找到一種方法來處理源,也不認爲這是必要的,因爲只有局部變量。然後將emails -list的結果存儲在數據庫中。在我添加此功能之前,我的工具的內存使用情況很穩定,現在每小時增長10Mb左右(取決於某人的電子郵件數量)。

任何建議非常感謝!

+0

如果您只需要在某個日期收到的電子郵件數量,您是否需要存儲它們?這可能會節省相當多的時間和空間。 –

+0

不,我不需要它。但是我需要改變什麼?謝謝! – casaout

回答

2

你可以在這裏嘗試的幾件事情:

  • 降低您的頁面大小。你一次只能做500個(.Take(500)),你可以試着減少這個。
  • 僅請求您感興趣的屬性。如果您修改.Select以引用m變量的特定屬性,API應在API請求中使用$select查詢參數來限制返回的內容。一個例子見this tutorial
+0

謝謝傑森!即使我在Select語句中選擇了一些屬性,我可以刪除所有這些屬性,因爲我不需要它們來計數。此外,我現在實施了適當的分頁(並減少了Take(500)Take(20)。我剛發佈了更新,並希望這可以修復用戶的所有內存問題。 – casaout