Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   C# Threads und BackgroundWorker (https://www.delphipraxis.net/110126-threads-und-backgroundworker.html)

Luckie 14. Mär 2008 09:24

Re: Threads und BackgroundWorker
 
Es sollen nur Demos für mich sein, um zu verstehen, wie Threads unter .NET funktionieren.

Wenn ich es jetzt wie vorgeschlagen mache, bekomme ich folgende Fehlermeldung:
Zitat:

Dieser BackgroundWorker gibt an, dass er keinen Fortschritt meldet. Ändern Sie WorkerReportsProgress, um anzugeben, dass er einen Fortschritt meldet.
Mein Code:
Code:
private void button1_Click(object sender, EventArgs e)
        {
            if (rbThread.Checked)
            {
                Thread t = new Thread(ThreadProc);
                t.Start();              
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish");
            }
            else
            {
                backgroundWorker1.RunWorkerAsync();
            }           
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 1000; i++)
            {
                backgroundWorker1.ReportProgress((int)i / 10);
               
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblStatusText.Text = resManager.GetString("BkWorkerStatusRunning");
        }

Elvis 14. Mär 2008 10:09

Re: Threads und BackgroundWorker
 
Ich selbst bin ein Fan vom BeginInvoke/EndInvoke Pattern.
Ich kann dadurch X Operationen asynchron starten, andere Dinge erledigen, und dann wenn ich das Ergebnis brauche, wartet der Code halt auf den Rückgabewert oder er hat ihn schon.

Das ganze lässt sich auch so verpacken, dass man sich eine Factory für Delegates baut, die dann entweder warten oder den bestehenden Wert zurück geben.

Um nicht soviel drumrum posten zu müssen, habe ich es mal nur mit lokalen Delegates gelöst: (Kein Delphi Code!)
Delphi-Quellcode:
var r : Random := new Random();

var myCall := method(parameter1, parameter2 : String) : Integer;
begin
  Thread.Sleep(5000);
  exit r.Next(0, 1000);
end;

var getAsyncCall := method(parameter1, parameter2 : String) : Func<Integer>;
begin
  var resultRef := new class(Value := default(nullable Integer));
  var getValue : AsyncCallback := method(ar : IAsyncResult);
  begin
    locking resultRef do
      if not assigned(resultRef.Value) then
        resultRef.Value := myCall.EndInvoke(ar);
  end;

  var call := myCall.BeginInvoke(parameter1,
                                 parameter2,
                                 getValue,
                                 nil);
  result := method : Integer;
  begin
    getValue(call);
    exit valueOrDefault(resultRef.Value);
  end;
end;

var async1 := getAsyncCall('abc', 'def');
var async2 := getAsyncCall('ghi', 'jkl');

// do soemthing...
Thread.Sleep(2500);

var result1 := async1();
var result2 := async2();
var result3 := async1();
Mit Futures wird das dann schon zu einem totalen no-brainer. :-)
Delphi-Quellcode:
var future1 := async myCall('abc', 'def');
var future2 := async myCall('ghi', 'jkl');

Luckie 14. Mär 2008 10:13

Re: Threads und BackgroundWorker
 
Langsam, langsam langsam. Anstatt mit immer neuen Lösungen zu kommen, wäre es mir lieb, wenn wir erstmal meine Probleme mit den vorhandenen Lösungen besprechen könnten.

Jürgen Thomas 14. Mär 2008 10:18

Re: Threads und BackgroundWorker
 
Hallo Michael,

Zitat:

Zitat von Luckie
Wenn ich es jetzt wie vorgeschlagen mache, bekomme ich folgende Fehlermeldung:
Zitat:

Dieser BackgroundWorker gibt an, dass er keinen Fortschritt meldet. Ändern Sie WorkerReportsProgress, um anzugeben, dass er einen Fortschritt meldet.

Anscheinend versteht der Compiler (oder passiert es doch zur Laufzeit?), dass Deine Fortschrittsmeldung statisch ist, aber nicht den aktuellen Status verwendet. Ändere diese Methode etwa so:

Code:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lblStatusText.Text = e.ProgressPercentage.ToString()
        + resManager.GetString("BkWorkerStatusRunning");
}
Das kann natürlich mit String.Format() o.a. sehr verschönert werden. Das Prinzip ist aber, dass Du über ProgressChangedEventArgs.ProgressPercentage den aktuellen Stand (wie er über ReportProgress gesetzt wird) und über ProgressChangedEventArgs.UserState sogar einen bestimmten Wert (z.B. den aktuellen Datensatz, der natürlich ebenfalls gesetzt werden müsste) erhältst.

Gruß Jürgen

Luckie 14. Mär 2008 10:43

Re: Threads und BackgroundWorker
 
Es passiert zur Laufzeit und zwar in dieser Zeile:
Code:
backgroundWorker1.ReportProgress((int)i / 10);
Deine Lösung dürfte also das Problem nicht beheben.

Elvis 14. Mär 2008 10:51

Re: Threads und BackgroundWorker
 
Zitat:

Zitat von Luckie
Es passiert zur Laufzeit und zwar in dieser Zeile:
Code:
backgroundWorker1.ReportProgress((int)i / 10);
Deine Lösung dürfte also das Problem nicht beheben.

Hast du denn die Eigenschaft gesetzt, die er dir da als nicht gesetzt gemeldet hat?

Alter Mann 14. Mär 2008 11:02

Re: Threads und BackgroundWorker
 
Hi Luki,

in der MSDN gibt es ein leicht verständliches Beispiel zum BackgroundWorker, nennt sich:
"Ausführen eines Vorgangs im Hintergrund" und ist unter Beispiele BackgroundWorker-Klasse zu finden.

Luckie 14. Mär 2008 11:04

Re: Threads und BackgroundWorker
 
Zitat:

Zitat von Elvis
Hast du denn die Eigenschaft gesetzt, die er dir da als nicht gesetzt gemeldet hat?

Ich versinke dann mal eben im Boden - bin gleich wieder da.

Luckie 14. Mär 2008 11:56

Re: Threads und BackgroundWorker
 
So wir haben es gleich geschafft. Nur noch zwei, drei Dinge.

Ich rufe die Methode CancelAsync() auf, um den BackgroundWorker zu stoppen. Allerdings schein dann das Fenster nicht mehr zu reagieren und gestoppt wird anscheinen auch nichts:
Code:
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (backgroundWorker1.CancellationPending)
            {
                lblStatusText.Text = resManager.GetString("BkWorkerUserCancel");
                e.Cancel = true;
            }
            for (int i = 0; i < 10000000; i++)
            {
                backgroundWorker1.ReportProgress((int)i / 10);
                Thread.Sleep(0);
               
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblStatusText.Text = resManager.GetString("BkWorkerStatusRunning");
            this.Update();
        }       

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblStatusText.Text = resManager.GetString("BkWorkerStatusFinish");
        }

Elvis 14. Mär 2008 12:02

Re: Threads und BackgroundWorker
 
Wo in deinem Code prüfst du denn, dass er abrechen soll?
Außer direkt am Anfang vor der Schleife natürlich... ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:08 Uhr.
Seite 2 von 4     12 34      

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