I am using VC++ Beta 2, with Windows Forms. I want to run a process in the background, leaving the UI responsive, and also to update a text box on the UI with interim progress data from my process. I have found a way to initiate a worker thread on the NET - as below.
using
namespace System;using
namespace System::Threading;public
ref class ThreadExample{
public: static void ThreadProc(){
//Do stuff}
};
void
RunProcess(){
Thread^ oThread =
gcnew Thread( gcnew ThreadStart( &ThreadExample::ThreadProc ) );oThread->Start();
}
RunProcess starts the thread fine, but I can't do anything with the process (get data from it to the UI, or cancel it) once it's started. I read that Windows Forms provides a class to sort this stuff out - the backgroundWorker component, but all of the examples I've seen of its use are in C# or VB. I'm not at all familiar with these languages, so my attempts to "convert" them have not gone well. What I really need is a walk-through, or a little example in the correct syntax, to get me going - can anyone direct me to one
Thanks.
Tom

Sorted
Lila44602
Disclaimer A: I'm not using beta 2 of VS (I'm on the final release). Disclaimer B: If it ain't broke, don't fix it.
It is true you can use BackgroundWorker to report progress/status and optionally cancel a worker thread cleanly (at the end of one iteration, you need to call ReportProgress() and check if CancellationPending==true).
I can't remember if the beta 2 help included a C++ code example for the BackgroundWorker, but I definitely know that the current help does have one. Check it out at: http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx.
benlung
Take a look at the second overload of ReportProgress(Int32, Object ^). The second parameter of this overload, an Object ^, allows you to pass your array to the callback (without the need of a global). Although the docs recommend you pass your this pointer as the second parameter, you can actually pass in anything as the second parameter.
In your case, you'd want that be the array, or some struct which contains your values (and any information which could be useful).
Satish Chandran
Magnus Hedin
Robert-IS
Leif Lundgren
I've also discovered that in some circumstances, when I run the programme with no breakpoints, it throws up an error - here's the error:
///////////////////////////
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Drawing.dll
Additional information: Index was outside the bounds of the array.
/////////////////////////////
I'm obviously doing something wrong here... Can anyone point me toward an answer
Tom
Comrad78
Okay... So I've got the thing working, but still run into some problems. I'm trying to send back data (formatted text) from the worker thread to update a text box. I assumed I can do this with the OnProgressChanged event, called using worker->reportprogress(). But I couldn't work out how to get textual, user defined information through to the event. So I added a global array, which I update directly, and which the OnProgressChanged event then reads before updating the text box... I worry that I may be breaking some rule here.
This is the code:
private
: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) { // Get the BackgroundWorker that raised this event.BackgroundWorker^ worker =
dynamic_cast<BackgroundWorker^>(sender);Body(worker, e ); //The shell for my main computation
}
private
: System::Void backgroundWorker1_ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e) {System::String^ NewString;
for(int s=0;s<3;s++){
NewString += System::Convert::ToString(ProgressVals
);
NewString += "\t";
}
NewString += "\r\n";
this->TextBox_Output->Text += NewString;}
//Called from somewhere in my code, I've passed the "worker" variable through all the way from the initial DoWorkEvent.
void PrintProgress(int Batches, double ErrorRate, double MaxDelta, BackgroundWorker^ worker){
ProgressVals[0] = Batches;
ProgressVals[1] = ErrorRate;
ProgressVals[2] = MaxDelta;
worker->ReportProgress(0);
}
I get some very strange stuff happening here, which makes me thing the method is fundamentally wrong. If I set a break point at the call to "Body()", then follow the execution into that function by pressing "f11", the thing seems to work fine. But if I do not set that break point, the whole application freezes and I have to force it off. I can't see why these two situations should produce such different results - any ideas
Any help on this would be much appreciated.
Tom