【问题标题】:Runtime Thread Access Violation Errors运行时线程访问冲突错误
【发布时间】:2019-08-12 19:32:20
【问题描述】:

我的想法是从字符串列表中的文件夹和子文件夹中下载所有文件。

接下来,我使用 SHGetFileInfo 函数检索名称并键入文件中的日期和链接以加载到我的 Access 数据库中。

我的应用程序工作正常,但是当我使用包含数百个文件的大文件夹时,它会阻止我使用线程所需的内容。

当我使用线程并且我的表为空时,它会显示错误消息,但是当我的表包含记录时,它第二次显示没有问题。

搜索过程

procedure FileSearche(const PathName: string; var lstFiles: TStringList);
const
  FileMask = '*.*';
var
  Rec: TSearchRec;
  Path: string;
begin
  Path := IncludeTrailingBackslash(PathName);
  if FindFirst(Path + FileMask, faAnyFile - faDirectory, Rec) = 0 then
    try
      repeat

        lstFiles.Add(Path + Rec.Name);
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;

  if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
    try
      repeat
        if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name <> '.') and
          (Rec.Name <> '..') then
          FileSearche(Path + Rec.Name, lstFiles);
      until FindNext(Rec) <> 0;
    finally
      FindClose(Rec);
    end;
end;

线程的过程

//--------------------------------------------------------------
{ debloc }

procedure debloc.execute;
var
  icn: HICON;
  SHFileInfo: TSHFileInfo;
  SearchRecord: TSearchRec;
  Size, I: Integer;
  lstFiles: TStringList;
  State: SHELLSTATE;
  lien, path: string;
  isEmpty : boolean;
begin
// to request windows to display the extension of all files

SHGetSetSettings(State, SSF_SHOWEXTENSIONS, false);
  State.Data := State.Data or SSF_SHOWEXTENSIONS;
  SHGetSetSettings(State, SSF_SHOWEXTENSIONS, True);
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, nil, nil);

// for select folder 

  if SelectDirectory('Choisi un dossier ', ' ', path) then
    Lien := IncludeTrailingPathDelimiter(path) else exit;
    isEmpty := IsDirectoryEmpty(path) ;

// To verify that the folder is not empty
    if isEmpty = false then
    Begin
    if MessageDlg('Remarque Le dossier :'+#13+path +#13+'est vide il n y pas des fichiers à importer', mtInformation,
    [mbOK], 0, mbOK) = mrOk then
    exit;
    End;

// To verify that the folder is not folder systeme
  if
     (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_WINDOWS)))
  or (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_SYSTEM)))
  or (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_PROGRAM_FILES)))
  or (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_PROGRAM_FILESX86)))
  or (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_MYPICTURES)))
  or (Lien = IncludeTrailingPathDelimiter(SpecialFolder(CSIDL_PROGRAM_FILES_COMMONX86)))
  or (Lien = 'C:\')
  then
  begin
//    ShowMessage(Lien+#13+'Erro, Les dossiers système sont ignoré pour votre sécurité');
    if MessageDlg(Lien+#13+'Attention, Pour des raison de sécurité les dossiers système sont ignoré ', mtWarning,
    [mbYes], 0, mbYes) = mrYes then
    exit;
  end
  else
begin
//To list the files in the StringList
  begin
    lstFiles := TStringList.Create;
    FileSearche(lien, lstFiles);
  end;

  if lstFiles.Count > 0 then
    for I := 0 to lstFiles.Count - 1 do

    begin
//To get the name, type, date, links of all files
        SHGetFileInfo(PChar(lstFiles[I]), 0, SHFileInfo, SizeOf(TSHFileInfo),
        SHGFI_TYPENAME or SHGFI_DISPLAYNAME or SHGFI_SYSICONINDEX or
        SHGFI_ICON);

      FindFirst(lstFiles[I], 0, SearchRecord);
      Size := SearchRecord.Size;

//To fill the Field of the table

      Form1.FDTable1.Edit;
      Form1.FDTable1.Insert;

      Form1.FDTable1.FieldByName('nom_file').ASSTRING := (SHFileInfo.szDisplayName);
      Form1.FDTable1.FieldByName('type_file').ASSTRING := (SHFileInfo.szTypeName);
      Form1.FDTable1.FieldByName('size_file').ASSTRING := (GetFileSizeAsString(Size));
      Form1.FDTable1.FieldByName('date_time_file').ASSTRING :=
        (DateTimeToStr(FileDateToDateTime(SearchRecord.Time)));
      Form1.FDTable1.FieldByName('lien_file').ASSTRING :=
        (ExtractFilePath(lstFiles[I]));

      Form1.ProgressBar1.Max := Form1.FDTable1.RecordCount;
      Form1.ProgressBar1.Position := Form1.FDTable1.RecordCount;
    end ;

  Form1.FDTable1.Post;
  Form1.FDTable1.First;

Form1.StatusBar1.Panels[0].Text := 'Nombre d"enregistrements: ' +
    IntToStr(Form1.FDTable1.RecordCount);

// to request windows to hide the extension of all files
  SHGetSetSettings(State, SSF_SHOWEXTENSIONS, false);
  State.Data := State.Data and ($FFFFFFFF xor SSF_SHOWEXTENSIONS);
  SHGetSetSettings(State, SSF_SHOWEXTENSIONS, True);
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, nil, nil);
// procedure to rearrange the automatic columns 
 SetGridColumnWidths(Form1.dbgrid1);
  Application.ProcessMessages;
end;
end;

执行线程

procedure TForm1.Button1Click(Sender: TObject);
BEGIN
 with debloc.Create do
  FreeOnTerminate:=true;
END;

当我使用线程并且表为空时,它会显示错误消息

违反 d'accès à l'adresse 00732BB1

但是第二次,当我的表被保存时,就没有问题了。

注意:尽管这段代码让我很恼火,但该应用程序的工作原理是一样的 另一件事我不知道当文件夹很大时如何停止线程。我关闭了停止的应用程序。

【问题讨论】:

  • 您无法从线程访问 UI 对象。将所有这些代码移出您的线程。即使您修复了代码看起来到处都是错误。
  • 如您所见,我不能在此应用程序中使用线程
  • 您无法从线程访问Form1。您也无法访问Form1.StatusBar1 或其面板,或与用户界面相关的任何其他内容(根本没有 VCL 控件)。这在帮助中有记录,在以前的线程问题中至少讨论了数十次,并且可以通过简单的 Google 搜索轻松获得。如果您在 IDE 中使用File-&gt;New-&gt;Other-&gt;Thread Object,源代码中也会提到,在生成代码顶部的大注释块中。如果所有这些都没有说清楚,不要触摸除主线程之外的任何可视控件

标签: multithreading delphi-2010


【解决方案1】:

我通过将 dbgrid 组件替换为 listview 组件解决了这个问题

procedure debloc.transfertdata;
var
Myitem : TListItem;
MyColumn : TListColumn;
begin
  ListView1.Items.Clear;
  ListView1.Columns.Clear;

  MyColumn:= ListView1.Columns.Add;
  MyColumn.Caption:= 'Nom' ;
  MyColumn.Width := -1;

  MyColumn:= ListView1.Columns.Add;
  MyColumn.Caption:= 'Type' ;
  MyColumn.Width := -1;

  MyColumn:= ListView1.Columns.Add;
  MyColumn.Caption:= 'Taille' ;
  MyColumn.Width := -1;

  MyColumn:= ListView1.Columns.Add;
  MyColumn.Caption:= 'Date de modification' ;
  MyColumn.Width := -1;

  MyColumn:= ListView1.Columns.Add;
  MyColumn.Caption:= 'Lien' ;
  MyColumn.Width := -1;

  FDTable1.First;
  while not FDTable1.Eof  do
  begin
    ListView1.Items.BeginUpdate;
    Myitem := ListView1.items.Add;
    Myitem.Caption:= FDTable1.FieldByName('nom_file').ASSTRING;
    Myitem.SubItems.Add(FDTable1.FieldByName('type_file').ASSTRING) ;
    Myitem.SubItems.Add(FDTable1.FieldByName('size_file').ASSTRING) ;
    Myitem.SubItems.Add(FDTable1.FieldByName('date_time_file').ASSTRING) ;
    Myitem.SubItems.Add(FDTable1.FieldByName('lien_file').ASSTRING) ;
    FDTable1.Next;
    ListView1.Items.EndUpdate;
  end;

end;

在我添加的线程中

 Synchronize(transfertdata);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多