在 C# 中通过 EWS API 下载附件非常缓慢 - 如何加快速度?



我正在使用 C# 中的 EWS 托管 API 从我公司的 Exchange 服务器下载一堆消息。加载消息本身需要很长时间,因为service.FindItems()只获取有关消息的有限信息,但这没什么大不了的。我面临的严重问题是加载附件需要多长时间。

该程序应该并排显示电子邮件及其图像附件。加载新电子邮件时,加载附件可能需要一分钟多的时间。我最初在加载邮件时获取每封邮件的附件,但我认为最好尝试将它们一次全部加载到List<EmailMessage>这样程序在加载单个邮件时就不必获取附件。

这是我用来执行此操作的代码:

fetchView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
fetchView.Traversal = FolderTraversal.Deep;
//create itemView for actual message query since we finally found the damn folder
ItemView iView = new ItemView(int.MaxValue);
FolderId sharedInboxFolder = new FolderId(WellKnownFolderName.Root, sharedMailbox);
FolderId targetFolder = new FolderId(WellKnownFolderName.Root, sharedMailbox);

FindFoldersResults inboxFolders = service.FindFolders(sharedInboxFolder, fetchView);
bool folderFound = false;
//look through the folders in the inbox to find the user-specified one by name
foreach(Folder f in inboxFolders)
{
if (f.DisplayName == Properties.Settings.Default.InboxFolder)
{
targetFolder = f.Id;
folderFound = true;
}
}

// Set itemview properties for FindItems() operation
fullProperties.Add(ItemSchema.Body);
fullProperties.Add(ItemSchema.Attachments);
fullProperties.Add(ItemSchema.DateTimeReceived);
fullProperties.Add(ItemSchema.Subject);

if (!folderFound)
{
MessageBox.Show("Folder not found!");
} else {
SearchFilter greaterthanfilter = new SearchFilter.IsGreaterThanOrEqualTo(ItemSchema.DateTimeReceived, searchDate);
SearchFilter lessthanfilter = new SearchFilter.IsLessThan(ItemSchema.DateTimeReceived, searchDate.AddDays(1));
SearchFilter dayFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, greaterthanfilter, lessthanfilter);
FindItemsResults<Item> fetchedMessages = service.FindItems(targetFolder, dayFilter, iView);
foreach (Item i in fetchedMessages.Items)
{
EmailMessage msg = EmailMessage.Bind(service, i.Id, fullProperties);
emails.Add(msg);
}
}
}

然后,我将所有附件保存到磁盘

for (int i = 0; i < message.Attachments.Count; i++)
{
if (message.Attachments[i] is FileAttachment)
{
FileAttachment att = message.Attachments[i] as FileAttachment;
att.Load();
using (FileStream attStream = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"Programimages" + i.ToString(), FileMode.Create, FileAccess.ReadWrite))
{ 
att.Load(attStream);
attStream.Close();
attStream.Dispose();
}
}
else
{
MessageBox.Show("Not FileAttachment!");
}
}

然后,要加载图像及其附件,我这样做

imgViewer.Source = new BitmapImage(new Uri(/some/path/to/image/))

我怀疑挂断是在保存附件阶段。我发现这篇文章表明应该禁用 TraceFlags,所以我做了service.TraceFlags = TraceFlags.None但这似乎根本没有帮助。我正在考虑预先下载所有附件,或者找出某种缓存机制,在用户处理消息[n]时,我在后台下载消息[n+1...x]的附件,但这用途有限,因为程序还应该让用户选择一个图像并相对即时地加载它(即不到一分钟(。

任何建议都非常感谢。

您无缘无故地加载附件两次。 从if (message.Attachments[i] is FileAttachment)语句中删除att.Load();

也许看看实现分页,反过来考虑将ItemViewpageSize减少到 1000 或更少的批次,而不是MaxValue

还要确保只返回属性集中所需的内容。BasePropertySet.FirstClassProperties考虑将其更改为仅返回所需的内容。

旁注:识别性能缓慢的代码的一个好方法是使用 .Net 秒表类。

Stopwatch sw = new Stopwatch();
sw.Start();
// code
sw.Stop();
StopWatchLog stopWatchLog = new StopWatchLog();
stopWatchLog.CreateXMLTextFile("MethodName()" + " took" + sw.Elapsed.Seconds + " seconds.");

最新更新