Загрузка приложений через EWS API в C # мучительно медленная - как ускорить? - PullRequest
0 голосов
/ 09 июня 2018

Я использую EWS Managed API в C #, чтобы загрузить кучу сообщений с сервера обмена моей компании.Загрузка самих сообщений занимает много времени, учитывая, что 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) + @"\Program\images\" + 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 + 1 ... x] в фоновом режиме, пока пользователь работает над сообщением [n], ноэто имеет ограниченную полезность, поскольку программа также должна позволять пользователю выбирать изображение и загружать его относительно мгновенно (т. е. намного меньше минуты).

Любые предложения приветствуются.

1 Ответ

0 голосов
/ 11 июня 2018

Ваша загрузка приложений дважды без видимой причины.Удалите att.Load(); из вашего оператора if (message.Attachments[i] is FileAttachment).

Может быть, стоит взглянуть на реализацию подкачки и, в свою очередь, рассмотреть возможность сокращения ItemView pageSize до пакетов по 1000 или менее,вместо MaxValue

Также убедитесь, что вы возвращаете только то, что вам нужно в вашем PropertySet .BasePropertySet.FirstClassProperties Попробуйте изменить это, чтобы просто вернуть то, что вам нужно.

Примечание: Хороший способ идентифицировать медленно работающий код - использовать класс .Net Секундомер ..

Stopwatch sw = new Stopwatch();
sw.Start();
// code
sw.Stop();
StopWatchLog stopWatchLog = new StopWatchLog();
stopWatchLog.CreateXMLTextFile("MethodName()" + " took" + sw.Elapsed.Seconds + " seconds.");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...