用COM完成耗时任务时防止崩溃(SKYPE4COM)

时间:2011-03-19 19:28:37

标签: delphi com activex skype

我正在使用Skype4COM控件。我的程序试图使用For循环从Skype中的联系人列表中删除大约3K个联系人,但是

1)需要很多时间

2)它可能会崩溃,“MyApp已停止工作”

我的猜测是,我需要“减慢”我正在做的事情。

我会用Sleep()做到这一点吗?因为我不确定这是否会“暂停”Skype和我的程序之间的连接。

总结一下:我正在用大量的条目做一个动作,由于这个大的数量,我的程序挂了很长时间,并最终崩溃(有时)。有没有办法防止这种情况?

Skype4COM顺便提一下STA。

  • 谢谢!

2 个答案:

答案 0 :(得分:6)

将处理移动到单独的线程中。您的问题似乎是Windows认为应用程序已停止响应,因为它没有处理它的消息循环。

调用Application.ProcessMessages是错误的解决方案,因为它比您想象的要多得多。您最终可能会遇到重入问题或者您不期望发生的事情。

确保线程在创建COM对象之前调用CoInitialize,并在完成后调用CoUnitialize。您可以在线程here中找到使用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;

答案 1 :(得分:0)

如果你使用循环来删除每个联系人,你可以调用Application.ProcessMessages这应该解决问题

[编辑] 调用应该在循环中