Rechenintensiver Workthread mit Progressbar (Umsetzung von C#/VB nach VC++)
From: Bernd Muent (kontakt_at_bmservices.de)
Date: 01/26/05
- Next message: Meier Rudolf: "Re: Templates in libraries?"
- Previous message: Klaus P. Pieper: "Re: CRecordset Feldwerte setzen ?"
- Next in thread: Martin Richter [MVP]: "Re: Rechenintensiver Workthread mit Progressbar (Umsetzung von C#/VBnach VC++)"
- Reply: Martin Richter [MVP]: "Re: Rechenintensiver Workthread mit Progressbar (Umsetzung von C#/VBnach VC++)"
- Messages sorted by: [ date ] [ thread ]
Date: Wed, 26 Jan 2005 12:41:22 +0100
Hallo zusammen,
ich hätte gerne ein GUI-Programm, in dem nach Drücken eines
Start-Knopfes mehrere umfangreiche Textdateien (etliche Megabyte)
bearbeitet werden. Derweil soll ein Zusatzfenster eingeblendet werden
mit einer ProgressBar und einem (funktionierenden!) Abbrechen-Button.
Alles funktioniert auch schon mit Ausnahme des Abbrechen-Buttons.
Ich hab mich an folgendem Example orientiert
(http://www.codeproject.com/cs/miscctrl/progressdialog.asp) und das
C#-Beispiel zunächst mal auf VB umgesetzt und auf die für mich
wesentlichen Dinge reduziert. Klappt auch wunderbar.
Wenn ich jetzt aber versuche, das ganze auf VC++ umzuzusetzen, stosse
ich auf etliche Detailschwierigkeiten.
Hat jemand einen Link zu einem Beispiel für VC++?
Wenn nein, dann kann mir vielleicht jemand bei den Details helfen?!
1. Aufruf des Work-Threads nach Klicken auf den Startbutton:
C#-Example:
System.Threading.ThreadPool.QueueUserWorkItem( new
System.Threading.WaitCallback( DoSomeWork ), progress );
Mein funktionierendes VB:
System.Threading.ThreadPool.QueueUserWorkItem(New
System.Threading.WaitCallback(AddressOf bearbeitung), progress)
C++:
System::Threading::ThreadPool::QueueUserWorkItem(new
System::Threading::WaitCallback(0,workThread),progress);
=> Der workThread wird niemals gestartet!
Das gleiche für:
System::Threading::ThreadPool::QueueUserWorkItem(new
System::Threading::WaitCallback(progress,workThread),progress);
System::Threading::ThreadPool::QueueUserWorkItem(new
System::Threading::WaitCallback(progress,workThread));
=> workThread läuft, kann aber nicht auf das Fenster mit der Progressbar
zugreifen: "Objektverweis auf keine Instanz").
2. Mein Working-Thread sieht in VB so aus:
Private Sub bearbeitung(ByVal status As Object)
Dim callback As IProgressCallback = status
Try
For i As Integer = 1 To 3
callback.setText("Bearbeite test" & i.ToString & ".txt")
callback.setBar(i / 3 * 100)
' do some work
If callback.isAborting Then
If Not (callback Is Nothing) Then
callback.destroy()
End If
Exit Sub
End If
Thread.Sleep(0)
Next
Catch ex As Exception
Catch ex As System.Threading.ThreadAbortException
Catch ex As System.Threading.ThreadInterruptedException
Finally
If Not (callback Is Nothing) Then
callback.destroy()
End If
End Try
End Sub
In C++ habe ich daraus gemacht:
void Form1::workThread(System::Object* status) {
IProgressCallback* callback=__try_cast<IProgressCallback*>(status);
try {
for (int i=1;i<=3;i++) {
callback->setText(String::Concat(S"Bearbeite
test",Convert::ToString(i),S".txt"));
// do some Work
if (callback->isAborting) {
if (callback != NULL) {callback->destroy();}
}
}
}
catch (Exception* ex) {
MessageBox::Show(ex->Message);
}
}
Dieser workThread kann leider niemals auf callback zugreifen und den
Text bzw. die Progressbar der Instanz der Klasse Progress verändern:
"Objektverweis ohne Instanz, wohl falsche Übergabe im QueueUserWorkItem
(s.o.)?!
3. Und dann bleibt noch meine Klasse Progress:
Dafür ist in VB zunächst ein Interface deklariert:
Public Interface IProgressCallback
Sub setText(ByVal text As String)
Sub setBar(ByVal val As Integer)
Sub destroy()
Property isAborting() As Boolean
End Interface
Das dann in die Klasse Progress mit
Public Class Progress
Inherits System.Windows.Forms.Form
Implements IProgressCallback
eingebunden wird.
In C++ habe ich daraus gemacht:
public __gc __interface IProgressCallback {
void setText(String* text);
void setBar(int val);
void destroy();
__property bool get_isAborting();
};
Nur irgendwie kriege ich dieses Interface nicht an die Klasse Progress
gebunden, "implements" oder ein Äquivalent habe ich nicht gefunden:
public __gc class Progress : public
System::Windows::Forms::Form,IProgressCallback
geht nicht.
In der Klasse gibt es in VB:
Public Delegate Sub setTextInvoker(ByVal text As String)
Public Delegate Sub stepProgressInvoker(ByVal val As Integer)
Das scheint in C++ auch so zu gehen:
public: __delegate void setTextInvoker(String* text);
public: __delegate void stepPrgressInvoker(int val);
Die Implementierungen der Interface-Teile sehen in VB so aus:
Public Overloads Sub setText(ByVal text As String) Implements
IProgressCallback.SetText
initEvent.WaitOne()
Invoke(New setTextInvoker(AddressOf doSetText), New Object()
{text})
End Sub
Da ist mir auch noch nicht so klar, wie ich das in C++ formulieren soll.
So, langer Text, vielleicht hat ja jemand Lust, mir den einen oder
anderen Tip zu geben.
Vielen Dank schon mal, Bernd
- Next message: Meier Rudolf: "Re: Templates in libraries?"
- Previous message: Klaus P. Pieper: "Re: CRecordset Feldwerte setzen ?"
- Next in thread: Martin Richter [MVP]: "Re: Rechenintensiver Workthread mit Progressbar (Umsetzung von C#/VBnach VC++)"
- Reply: Martin Richter [MVP]: "Re: Rechenintensiver Workthread mit Progressbar (Umsetzung von C#/VBnach VC++)"
- Messages sorted by: [ date ] [ thread ]