Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Background Intelligent Transfer Service nutzen (https://www.delphipraxis.net/153529-background-intelligent-transfer-service-nutzen.html)

NormanNG 6. Aug 2010 17:16

AW: Background Intelligent Transfer Service nutzen
 
Hi,

kann es sein, das in der Funktion TBackgroundCopyService.DownloadMultiUrl noch ein Fehler ist?
Ist die Scheife zum Befüllen von DownloadInfo nicht falsch?

Delphi-Quellcode:
function TBackgroundCopyService.DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent; var aError: WideString;
  const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
:
  ZeroMemory(@DownloadInfo, SizeOf(DownloadInfo));

  for nCount := Low(aURL) to High(aURL) do
  begin
    DownloadInfo.RemoteName := PWideChar(aUrl[nCount]);
    DownloadInfo.LocalName := PWideChar(aDest[nCount]);
  end;

  nCount := Length(aURL);
  Res := CopyJob.AddFileSet(nCount, DownloadInfo);
:

Luckie 6. Aug 2010 17:32

AW: Background Intelligent Transfer Service nutzen
 
Zitat:

Zitat von HeikoAdams (Beitrag 1040057)
Du immer mit Deinen Exceptions :-D Ich halte nicht viel davon, bei jedem Fehler eine Exception zu werfen.

Dann hast du den Sinn von Exceptions nicht verstanden. Was ist übersichtlicher:
Delphi-Quellcode:
try
  AufrufFunktion;
  AufrufFunktion;
  AufrufFunktion;
  AufrufFunktion;
  AufrufFunktion;
  AufrufFunktion;
except
  // Fehlerbehandlung
  on E: Exception do
    ShowMessage(E.Message); // Aussagekräftige Fehlermeldung aus Funktion, die Exception wirft
end;
oder

Delphi-Quellcode:
  if Anweisung then
    if Anweisung then
      if Anweisung then
        if Anweisung then
          if Anweisung then

          else
            // Fehlerbehandlung
         else
          // Fehlerbehandlung
      else
        // Fehlerbehandlung
    else
      // Fehlerbehandlung
  else
    // Fehlerbehandlung
Mittels Exceptions kann man fehler zentral an einer Stelle behandlen. Der Code wird damit einfachher lesbar, übersichtlicher und wartbarer.

Und noch was, wenn du schon objektorientiert programmierst, warum dann nicht auch bei der Fehlerbhandlung?

HeikoAdams 8. Aug 2010 12:08

AW: Background Intelligent Transfer Service nutzen
 
Zitat:

Zitat von Luckie (Beitrag 1040072)
Dann hast du den Sinn von Exceptions nicht verstanden.

Doch, ich habe den Sinn schon verstanden. Nur in diesem Fall halte ich Exceptions für überflüssig, weil ich ausschließlich API-Routinen nutze, die mir im Fehlerfall einen Fehlercode zurückliefern. Wenn ich eigene Funktionen schreibe, nutze ich sehr wohl Exceptions.

Luckie 8. Aug 2010 12:42

AW: Background Intelligent Transfer Service nutzen
 
Und was spricht dagegen im den Fehlercode zu prüfen und gegebenen falls eine Exception zu werfen? Guck dir doch den Spaghetti Code an der dabei rauskommt.

himitsu 8. Aug 2010 12:49

AW: Background Intelligent Transfer Service nutzen
 
in C/PHP ginge sowas :roll:

Code:
((($Result = AufrufFunktion1()) == S_OK) &&
 (($Result = AufrufFunktion2()) == S_OK) &&
 (($Result = AufrufFunktion3()) == S_OK) &&
 (($Result = AufrufFunktion4()) == S_OK) &&
 (($Result = AufrufFunktion5()) == S_OK));
return $Result;

HeikoAdams 9. Aug 2010 07:16

AW: Background Intelligent Transfer Service nutzen
 
Zitat:

Zitat von Luckie (Beitrag 1040242)
Und was spricht dagegen im den Fehlercode zu prüfen und gegebenen falls eine Exception zu werfen? Guck dir doch den Spaghetti Code an der dabei rauskommt.

Du meinst, anstelle von
Delphi-Quellcode:
  if not Succeeded(Res) then
  begin
    aError := WideString(SysErrorMessage(Res));
    Exit;
  end;
sowas
Delphi-Quellcode:
  if not Succeeded(Res) then
    RaiseLastOSError;
?

HeikoAdams 9. Aug 2010 07:44

AW: Background Intelligent Transfer Service nutzen
 
Okay, dann halt mit Exceptions: :-D
Delphi-Quellcode:
unit BackgroundCopyService;

interface

uses ExtActns, JwaWindows, Types, SysUtils;

type
  EInitServiceError = Exception;
  TBackgroundCopyService = class
  private
    FAttempts: Byte;
    CopyMngr: IBackgroundCopyManager;
    CopyJob: IBackgroundCopyJob;

    function DownloadUrl(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent; const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
    function DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
      const aDownloadFeedback: TDownloadProgressEvent;const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean; experimental;

    function WaitForDownload(const aJobType: BG_JOB_TYPE;
      const aDownloadFeedback: TDownloadProgressEvent): BG_JOB_STATE;
    function GetNewJob(const aDisplayName: WideString;
      const aJobType: BG_JOB_TYPE; var aJob: IBackgroundCopyJob): Integer;
    function GetCopyJobError: HRESULT;
    function ResumeJob(const aJobType: BG_JOB_TYPE; const aDownloadFeedback: TDownloadProgressEvent): Boolean;
  public
    constructor Create;
    destructor Destroy; override;

    function UploadFile(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent;const aDisplayName: WideString): Boolean;
    function DownloadFile(const aURL, aDest: WideString;
      const aDownloadFeedback: TDownloadProgressEvent;const aDisplayName: WideString): Boolean;
    function DownloadFiles(const aURL, aDest: TWideStringDynArray;
      const aDownloadFeedback: TDownloadProgressEvent;const aDisplayName: WideString): Boolean; experimental;

    property AttemptsOnFailure: Byte read FAttempts write FAttempts;
  end;

implementation

uses JclWin32, ComObj, JclSysInfo;

constructor TBackgroundCopyService.Create();
begin
  FAttempts := 3;
  CopyMngr := CreateComObject(CLSID_BackgroundCopyManager) as IBackgroundCopyManager;

  if not Assigned(CopyMngr) then
    raise EInitServiceError.Create('Initialization of BackgroundCopyService failed!');
end;

destructor TBackgroundCopyService.Destroy;
begin
  inherited;

  if Assigned(CopyJob) then
    CopyJob := nil;

  if Assigned(CopyMngr) then
    CopyMngr := nil;
end;

function TBackgroundCopyService.UploadFile(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadUrl(aURL, aDest, aDownloadFeedback, aDisplayName,
      BG_JOB_TYPE_UPLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.DownloadFile(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadUrl(aURL, aDest, aDownloadFeedback, aDisplayName,
      BG_JOB_TYPE_DOWNLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.DownloadFiles(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent;
  const aDisplayName: WideString): Boolean;
var
  nCount: Byte;
begin
  nCount := 1;

  repeat
    Result := DownloadMultiUrl(aURL, aDest, aDownloadFeedback,
      aDisplayName, BG_JOB_TYPE_DOWNLOAD);

    Inc(nCount);
  until Result or (nCount > FAttempts);
end;

function TBackgroundCopyService.GetNewJob(const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE; var aJob: IBackgroundCopyJob): Integer;
var
  JobId: TGUID;
begin
  Result := CopyMngr.CreateJob(PWideChar(aDisplayName), aJobType, JobId, aJob);
end;

function TBackgroundCopyService.GetCopyJobError: HRESULT;
var
  CopyError: IBackgroundCopyError;
  Context: BG_ERROR_CONTEXT;
begin
  CopyJob.GetError(CopyError);
  CopyError.GetError(Context, Result);
  CopyError := nil;
end;

function TBackgroundCopyService.ResumeJob(const aJobType: BG_JOB_TYPE;
  const aDownloadFeedback: TDownloadProgressEvent): Boolean;
var
  JobStatus: BG_JOB_STATE;
begin    
  Result := False;

  CopyJob.Resume();

  JobStatus := WaitForDownload(aJobType, aDownloadFeedback);

  if (JobStatus in [BG_JOB_STATE_TRANSFERRED,
    BG_JOB_STATE_ERROR, BG_JOB_STATE_TRANSIENT_ERROR]) then
  begin
    Result := (JobStatus = BG_JOB_STATE_TRANSFERRED);

    if not Result then
      RaiseLastOSError(GetCopyJobError);
  end;

  if (JobStatus = BG_JOB_STATE_TRANSFERRED) then
    CopyJob.Complete
  else
    CopyJob.Cancel;
end;

function TBackgroundCopyService.DownloadUrl(const aURL, aDest: WideString;
  const aDownloadFeedback: TDownloadProgressEvent;
  const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
begin
  if Assigned(CopyJob) then
    CopyJob := nil;

  if not Succeeded(GetNewJob(PWideChar(aDisplayName), aJobType, CopyJob)) then
    RaiseLastOSError;

  if not Succeeded(CopyJob.AddFile(PWideChar(aURL), PWideChar(aDest))) then
    RaiseLastOSError;

  Result := ResumeJob(aJobType, aDownloadFeedback);
  CopyJob := nil;
end;

function TBackgroundCopyService.DownloadMultiUrl(const aURL, aDest: TWideStringDynArray;
  const aDownloadFeedback: TDownloadProgressEvent;
  const aDisplayName: WideString;
  const aJobType: BG_JOB_TYPE = BG_JOB_TYPE_DOWNLOAD): Boolean;
var
  DownloadInfo: PBgFileInfo;
  Info: BG_FILE_INFO;
  nCount: Integer;
begin
  if Assigned(CopyJob) then
    CopyJob := nil;

  if not Succeeded(GetNewJob(PWideChar(aDisplayName), aJobType, CopyJob)) then
    RaiseLastOSError;

  ZeroMemory(@Info, SizeOf(Info));

  for nCount := Low(aURL) to High(aURL) do
  begin
    with Info do
    begin
      RemoteName := PWideChar(aUrl[nCount]);
      LocalName := PWideChar(aDest[nCount]);
    end;
  end;

  DownloadInfo := @Info;
  nCount := Length(aURL);

  if not Succeeded(CopyJob.AddFileSet(nCount, DownloadInfo)) then
    RaiseLastOSError;

  Result := ResumeJob(aJobType, aDownloadFeedback);
  CopyJob := nil;
end;

function TBackgroundCopyService.WaitForDownload(const aJobType: BG_JOB_TYPE;
  const aDownloadFeedback: TDownloadProgressEvent): BG_JOB_STATE;
var
  JobProgress: BG_JOB_PROGRESS;
  hTimer: THandle;
  DueTime: TLargeInteger;
  bCanceled: boolean;
begin
  bCanceled := False;    
  DueTime := -10000000;
  hTimer := CreateWaitableTimer(nil, false, 'EinTimer');
  SetWaitableTimer(hTimer, DueTime, 1000, nil, nil, false);

  while True do
  begin
    CopyJob.GetState(Result);

    if (Result in [BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_TRANSFERRED]) then
    begin
      CopyJob.GetProgress(JobProgress);

      if (aJobType = BG_JOB_TYPE_DOWNLOAD) then
        aDownloadFeedback(nil, JobProgress.BytesTransferred, JobProgress.BytesTotal,
          dsDownloadingData, '', bCanceled)
      else
        aDownloadFeedback(nil, JobProgress.BytesTransferred, JobProgress.BytesTotal,
          dsUploadingData, '', bCanceled);

      if bCanceled then
        break;
    end;

    if (Result in [BG_JOB_STATE_TRANSFERRED,
      BG_JOB_STATE_ERROR, BG_JOB_STATE_TRANSIENT_ERROR]) then
      break;

    WaitForSingleObject(hTimer, INFINITE);
  end;

  CancelWaitableTimer(hTimer);
  CloseHandle(hTimer);
end;

end.

NormanNG 9. Aug 2010 07:49

AW: Background Intelligent Transfer Service nutzen
 
Hi,

könnte bitte einmal jemand zu #11 Stellung nehmen?
Ist wohl bei aller Exception-Reiterei etwas untergegangen.

HeikoAdams 9. Aug 2010 07:57

AW: Background Intelligent Transfer Service nutzen
 
Zitat:

Zitat von NormanNG (Beitrag 1040335)
Hi,
könnte bitte einmal jemand zu #11 Stellung nehmen?

Was soll denn an der Befüllung von DownloadInfo falsch sein?

himitsu 9. Aug 2010 08:03

AW: Background Intelligent Transfer Service nutzen
 
Delphi-Quellcode:
var
  DownloadInfo: PBgFileInfo
Das sieht nach einem Pointer aus, welchem aber kein Speicher zugewiesen wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:27 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz