请教,怎么用线程来防止程序运行很耗时程序时的假死。

zhugeliangzhangfei 2010-06-20 02:06:07
如题,
我程序里需要运行一些很耗时的函数,一运行就会使得程序界面假死,或者出现界面的没反应
应该怎么做呢?
线程怎么写,怎么在线程里运用这些耗时的函数
目的,就是防止假死。
谢谢了
...全文
176 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
kakasalad 2011-02-18
  • 打赏
  • 举报
回复
我也困惑这个问题…一楼的示例代码好像没给全啊,几个步骤没看懂…
幻想多巴胺 2010-07-05
  • 打赏
  • 举报
回复
zhugeliangzhangfei 2010-06-20
  • 打赏
  • 举报
回复
type
TTestThread = class(TThread)
public
procedure MyGetWebImage;
procedure MyGetWebFlash;
procedure MyGetWebLinkUrl;
procedure MyGetWebVideo;
protected
procedure Execute; override;
end;

implementation
uses Unit_Function,UnitMain,Unit_CheckWebElements;

procedure TTestThread.MyGetWebImage;
var
Myhtml_doc: IHTMLDocument2;
Mydoc_all: IHtmlElementCollection;
vI : IHtmlImgElement;
i:Integer;
MylistViewItem:TListItem;
MyFileSize,MytemSize:integer;
MytempStr:string;
MyWebbrowse:TEmbeddedWB;
begin
FormCheckElements.ListView1.Items.Clear;
MyWebbrowse:=formtheworld.bsskinpagecontrol1.activepage.controls[0]as TEmbeddedWB;
if not MyWebbrowse.Busy then
begin
Myhtml_doc :=MyWebbrowse.Document as IHTMLDocument2;
Mydoc_all :=Myhtml_doc.images;
for i :=0 to Mydoc_all.length -1 do
begin
Application.ProcessMessages;
vI:=Mydoc_all.item(I,EMPTYPARAM) as IHtmlImgElement;
MytemSize:=StrToInt(vI.fileSize);
if MyIsItemsInListview(FormCheckElements.ListView1,vI.nameProp,vI.href)=false then
begin
if vI.nameProp<>'' then
begin
MylistViewItem:=FormCheckElements.ListView1.Items.Add;
MylistViewItem.Caption:=vI.nameProp;
MylistViewItem.SubItems.Add(vI.href);
try
if vI.mimeType='' then
begin
if vI.nameProp<>'' then
MylistViewItem.SubItems.Add(UpperCase(Copy(MyGetLastTextStr(vI.nameProp,'.'),1,12)))
end
else
MylistViewItem.SubItems.Add(vI.mimeType);
MyFileSize:=Round(MytemSize/1024);
if MyFileSize=0 then
MyFileSize:=1;
MylistViewItem.SubItems.Add(IntToStr(MyFileSize)+'KB');
MylistViewItem.SubItems.Add(IntToStr(vI.width)+'*'+inttostr(vI.height));
except
if vi.nameProp<>'' then
begin
MytempStr:=UpperCase(Copy(MyGetLastTextStr(vI.nameProp,'.'),1,12));
MylistViewItem.SubItems.Add(MytempStr);
MylistViewItem.SubItems.Add('-');
MylistViewItem.SubItems.Add('0*0');
end
else
begin
MytempStr:='-';
MylistViewItem.SubItems.Add(MytempStr);
MylistViewItem.SubItems.Add('-');
MylistViewItem.SubItems.Add('0*0');
end;
end;
end;
end;
end;
end;
end;

procedure TTestThread.MyGetWebFlash;
var
MyStrList:TStringList;
MyTemStrList:TStrings;
MyHtmlStr,Mytempstr,MyTemFilePath,MyFileName,MyStrs,MyTemStrs:string;
i,j,k,y,MyFileSize:Integer;
MylistViewItem:TListItem;
MyFileHandle:integer;
MyFlash: OleVariant;
MyWebbrowse:TEmbeddedWB;
MyFlashList:TStringList;
begin
FormCheckElements.ListView2.Items.Clear;
MyStrList:=Tstringlist.Create;
MyTemStrList:=TStringList.Create;
MyWebbrowse:=formtheworld.bsskinpagecontrol1.activepage.controls[0]as TEmbeddedWB;
if MyWB_GetHTMLCode(MyWebbrowse,MyTemStrList)then
MyHtmlStr:=MyTemStrList.Text;
try
if MyHtmlStr<>'' then
begin
if pos('.swf',LowerCase(MyHtmlStr))<>0 then
begin
MyGetWebFlashInfo(MyHtmlStr,MyStrList);
for i:=0 to pred(MyStrList.Count)do
begin
Application.ProcessMessages;
try
MyFileSize:=0;
Mytempstr:=MyStrList[i];
MyGetLocalFileNameFromIECache(Mytempstr,MyTemFilePath);
MyFileName:=LowerCase(MyGetLastTextStr(MyTempStr,'/'));
if MyIsItemsInListview(FormCheckElements.ListView2,MyFileName,Mytempstr)=False then
begin
MylistViewItem:=FormCheckElements.ListView2.Items.Add;
MylistViewItem.Caption:=MyFileName;
MylistViewItem.SubItems.Add(Mytempstr);
MylistViewItem.SubItems.Add(UpperCase(MyGetLastTextStr(MyTempStr,'.')));
if FileExists(MyTemFilePath)then
begin
MyFileHandle:=FileOpen(MyTemFilePath,0);
MyFileSize:=Round(GetFileSize(MyFileHandle,nil)/1024);
FileClose(MyFileHandle);
end;
MylistViewItem.SubItems.Add(IntToStr(MyFileSize)+'KB');
end;
except
end;
end;
end
else
begin
MyFlash:= MyWebbrowse.OleObject.document.getElementsByTagName('iframe');
for j := 0 to MyFlash.length - 1 do
begin
MyTemStrs:=LowerCase(MyFlash.item(j).src);
if Pos('http',MyTemStrs)<>0 then
begin
MyFlashList:=TStringList.Create;
MyGetWebFlashInfo(MyTemStrs,MyFlashList);
for y:=0 to pred(MyFlashList.Count)do
begin
MyStrs:=lowercase(MyGetWebPageHtmlText(MyFlashList[y]));
if pos('swf',MyStrs)<>0 then
begin
MyGetWebFlashInfo(MyStrs,MyStrList);
for k:=0 to pred(MyStrList.Count)do
begin
Application.ProcessMessages;
try
MyFileSize:=0;
Mytempstr:=MyStrList[k];
MyGetLocalFileNameFromIECache(Mytempstr,MyTemFilePath);
MyFileName:=LowerCase(MyGetLastTextStr(MyTempStr,'/'));
if MyIsItemsInListview(FormCheckElements.ListView2,MyFileName,Mytempstr)=False then
begin
MylistViewItem:=FormCheckElements.ListView2.Items.Add;
MylistViewItem.Caption:=MyFileName;
MylistViewItem.SubItems.Add(Mytempstr);
MylistViewItem.SubItems.Add(UpperCase(MyGetLastTextStr(MyTempStr,'.')));
if FileExists(MyTemFilePath)then
begin
MyFileHandle:=FileOpen(MyTemFilePath,0);
MyFileSize:=Round(GetFileSize(MyFileHandle,nil)/1024);
FileClose(MyFileHandle);
end;
MylistViewItem.SubItems.Add(IntToStr(MyFileSize)+'KB');
end;
except
end;
end;
end
else
break;
end;
MyFlashList.Free;
end;
end;
end;
end;
finally
MyTemStrList.Free;
MyStrList.Free;
end;
end;

procedure TTestThread.MyGetWebVideo;
var
MyVideo: OleVariant;
i: Integer;
MyTempStr,MyTemFilePath,MyFileName:string;
MyFileSize:Integer;
MylistViewItem:TListItem;
MyFileHandle:integer;
MyWebbrowse:TEmbeddedWB;
begin
FormCheckElements.ListView3.Items.Clear;
MyWebbrowse:=formtheworld.bsskinpagecontrol1.activepage.controls[0]as TEmbeddedWB;
MyFileSize:=0;
if not MyWebbrowse.Busy then
begin
MyVideo:= MyWebbrowse.OleObject.document.getElementsByTagName('embed');
for i := 0 to MyVideo.length - 1 do
begin
Application.ProcessMessages;
try
MyTempStr:=MyVideo.item(i).src;
MyGetLocalFileNameFromIECache(MyTempStr,MyTemFilePath);
if FileExists(MyTemFilePath)then
begin
MyFileHandle:=FileOpen(MyTemFilePath,0);
MyFileSize:=Round(GetFileSize(MyFileHandle,nil)/1024);
FileClose(MyFileHandle);
end;
MyFileName:=MyGetLastTextStr(MyTempStr,'/');
if MyIsItemsInListview(FormCheckElements.ListView3,MyFileName,MyTempStr)=False then
begin
if MyFileName<>'' then
begin
MylistViewItem:=FormCheckElements.ListView3.Items.Add;
MylistViewItem.Caption:=MyFileName;
MylistViewItem.SubItems.Add(MyTempStr);
MylistViewItem.SubItems.Add(UpperCase(MyGetLastTextStr(MyTempStr,'.')));
MylistViewItem.SubItems.Add(IntToStr(MyFileSize)+'KB');
MylistViewItem.SubItems.Add('-');
end;
end;
except
end;
end;
end;
end;

procedure TTestThread.MyGetWebLinkUrl;
var
vDoc: OLEVariant;
i: integer;
MylistViewItem:TListItem;
MyTemStr,MyTemStr1:string;
MyWebbrowse:TEmbeddedWB;
begin
FormCheckElements.ListView4.Items.Clear;
MyWebbrowse:=formtheworld.bsskinpagecontrol1.activepage.controls[0]as TEmbeddedWB;
if not MyWebbrowse.Busy then
begin
vDoc := MyWebbrowse.Document;
for i:=0 to vDoc.links.tags('a').length-1 do
begin
Application.ProcessMessages;
try
MyTemStr:=vDoc.links.tags('a').Item(i).href;
MyTemStr1:=MyGetLastTextStr(MyTemStr,'.');
if MyIsItemsInListview(FormCheckElements.ListView4,vDoc.links.tags('a').Item(i).innerText,vDoc.links.tags('a').Item(i).href)=False then
begin
if MyTemStr<>'' then
begin
MylistViewItem:=FormCheckElements.ListView4.Items.Add;
MylistViewItem.Caption:=(vDoc.links.tags('a').Item(i).innerText);
MylistViewItem.SubItems.Add(vDoc.links.tags('a').Item(i).href);
if MyTemStr1<>'' then
MylistViewItem.SubItems.Add(MyTemStr1);
end;
end;
except
end;
end;
end;
end;

procedure TTestThread.Execute;
begin
FreeOnTerminate:=True;
Synchronize(MyGetWebImage);
Synchronize(MyGetWebVideo);
Synchronize(MyGetWebFlash);
Synchronize(MyGetWebLinkUrl);
end;

我的程序时这样写的,
然后我在主程序的一个form中onshow事件中
创建一个线程,来运行函数
就是我的form一出现,就运行这些耗时函数,结果这个form出现后,主程序假死
我不想主程序假死,希望它能接受鼠标消息,
我上面的这些代码,有时候还是会造成假死,应该怎么改呢?
xray2005 2010-06-20
  • 打赏
  • 举报
回复
Thread th=new Thread(new ThreadStart(MyMethod));
th.IsBackGround=true;
th.Start();


private void MyMethod()
{
//耗时的处理
}

在辅线程中更新界面,需要使用Invoke,否则会出现:线程间操作无效: 从不是创建控件的线程访问它的错误。

比如:
private void SetText(string text)
{
// InvokeRequired需要比较调用线程ID和创建线程ID
// 如果它们不相同则返回true
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}


给你几个连接,看看就应该会了。

有趣的多线程编程
c#将数据传入ThreadStart中

小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法
mapserver 2010-06-20
  • 打赏
  • 举报
回复
多线程异步调用,代码如下:
ExecPingProcess,就相当于你的很费时间的方法,这个方法执行完成后,再去做PingCallBack的方法,来通知主线程。


private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = string.Empty;

ThreadStart start = new ThreadStart(Ping);
Thread t = new Thread(start);
t.Start();
}

private void Ping()
{
AsynPingDelegate caller = new AsynPingDelegate(this.ExecPingProcess);
AsyncCallback asyncPingCallback = new AsyncCallback(PingCallBack);

IAsyncResult result = caller.BeginInvoke(out output, PingCallBack, null);
result.AsyncWaitHandle.WaitOne();
caller.EndInvoke(out output, result);
}

private void ExecPingProcess(out string s)
{
Process p = new Process();

p.StartInfo.FileName = "ping";
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = textBox1.Text;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.Start();

StreamReader sr = p.StandardOutput;
s = sr.ReadToEnd();

p.WaitForExit();
p.Close();
}

private void PingCallBack(IAsyncResult result)
{
// 此处的目的是:确保UI线程间的安全。
MethodDelegate methodDelegate = new MethodDelegate(UpdateOutput);
this.Invoke(methodDelegate);
}

1,978

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 其他语言讨论
社区管理员
  • 其他语言社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧