Недавно я начал использовать новый Outlook/Office 365 Rest API и получил большую помощь в отношении аутентификация (новая модель приложения v2.0), области, используя OutlookServicesClient и лучше писать (linq-)queries.
К сожалению, некоторые пользователи сообщили о некоторых проблемах с памятью, которые привели к следующему 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
затем сохраняется в базе данных. Использование памяти для моего инструмента было стабильным до того, как я добавил эту функцию, и теперь растет примерно на 10 МБ в час (в зависимости от того, сколько у кого-то электронных писем).
Любые предложения очень ценятся!