Предотвращение сбоя при выполнении трудоемкой задачи с помощью COM (SKYPE4COM) - PullRequest
2 голосов
/ 19 марта 2011

Я использую элемент управления Skype4COM. Моя программа пытается удалить около 3K контактов из моего списка контактов в Skype, используя цикл For, однако

1) Это занимает много времени

2) может произойти сбой, с «MyApp перестал работать»

Я предполагаю, что каким-то образом мне нужно "замедлить" то, что я делаю.

Буду ли я делать это с Sleep () ;? Потому что я не уверен, что это "приостановит" соединение между Skype и моей программой.

Подводя итог: я выполняю действие с огромным количеством записей, и из-за этого большого количества моя программа зависает в течение длительного времени, и в конечном итоге происходит сбой (иногда). Есть ли способ предотвратить это?

Кстати, Skype4COM - это STA.

  • Спасибо!

Ответы [ 2 ]

6 голосов
/ 19 марта 2011

Переместить обработку в отдельный поток.Похоже, ваша проблема в том, что Windows думает, что приложение перестало отвечать, потому что оно не обрабатывает цикл сообщений.

Вызов Application.ProcessMessages - неправильное решение, потому что он делает намного больше, чем вы думаете.Вы можете столкнуться с проблемами с повторным входом или с событиями, которые вы не ожидаете.

Убедитесь, что поток вызывает CoInitialize , прежде чем он создает объект COM, и вызывает Коинициализировать когда это будет сделано.Вы можете найти примеры использования COM в потоке здесь ;статья ссылается на ADO, но демонстрирует использование CoInitialize/CoUninitialize.

РЕДАКТИРОВАТЬ: После комментариев я добавляю пример получения настраиваемого сообщения в приложении Delphi.Потоку потребуется доступ к константе UM_IDDELETED;Вы можете сделать это, (предпочтительно) добавив его к отдельному модулю и используя этот модуль как в модуле вашей основной формы, так и в модуле потока, или просто определив его в обоих модулях.

// uCustomMsg.pas
const
  UM_IDDELETED = WM_APP + 100;

// Form's unit
interface

uses ..., uCustomMsg;

type
  TForm1=class(TForm)
  // ...
  private
    procedure UMIDDeleted(var Msg: TMessage); message UM_IDDELETED;
  //...
  end;

implementation

procedure TForm1.UMIDDeleted(var Msg: TMessage);
var
  DeletedID: Integer;
begin
  DeletedID := Msg.WParam;
  // Remove this item from the tree
end;

// Thread unit
implementation

uses
  uCustomMsg;

// IDListIdx is an integer index into the list or array
// of IDs you're deleting.
// 
// TheFormHandle is the main form's handle you passed in
// to the thread's constructor, along with the IDList
// array or list.

procedure TYourThread.Execute;
var
  IDToDelete: Integer;  // Your ID to delete
begin
  while not Terminated and (IDListIdx < IdList.Count) do
  begin
    IDToDelete := IDList[IDListIdx];
    // ... Do whatever to delete ID
    PostMessage(TheFormHandle, UM_IDDELETED, IDToDelete, 0);
  end;
end;
0 голосов
/ 19 марта 2011

если вы используете цикл для удаления каждого контакта, вы можете сделать вызов Application.ProcessMessages, это должно решить проблему

[edit] вызов должен быть в цикле

...