当前位置:编程学习 > C#/ASP.NET >>

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

如题,
我程序里需要运行一些很耗时的函数,一运行就会使得程序界面假死,或者出现界面的没反应
应该怎么做呢?
线程怎么写,怎么在线程里运用这些耗时的函数
目的,就是防止假死。
谢谢了 --------------------编程问答-------------------- 多线程异步调用,代码如下:
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);
        }
--------------------编程问答-------------------- 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中

小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法 
--------------------编程问答-------------------- 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出现后,主程序假死
我不想主程序假死,希望它能接受鼠标消息,
我上面的这些代码,有时候还是会造成假死,应该怎么改呢?
--------------------编程问答-------------------- --------------------编程问答-------------------- 我也困惑这个问题…一楼的示例代码好像没给全啊,几个步骤没看懂…
补充:.NET技术 ,  其他语言
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,