This is my first post here and I'm brand new to .NET. I'm creating a Windows Forms application using C++/CLI that needs to have bidirectional communication with several worker threads. I read the tutorials on the background threads and created a simple Form with a TextBox that starts several background workers (bw's). Each of the bw runs a do-forever loop that occasionally sends a data structure to the Form using bw->ReportProgress(0, my_data_structure), and the Form's ProgressChanged() event formats the data into a string that it Appends to the TextBox.
All this was working well but I needed a way for the Form to send data to the bw's. Named Pipes seemed to be a reasonable way to do this, but i can't get it to work.
In Form1.h, I added private variables:
private:
System::IO::Pipes::NamedPipeServerStream ^pipeServer;
array<byte> ^msgOut;
Then in Form1 c'tor:
Form1(void)
{
InitializeComponent();
this->msgOut = (gcnew array<byte>(256));
this->pipeServer = (gcnew NamedPipeServerStream("pipeStream1", PipeDirection::Out));
this->Arm1Thd->RunWorkerAsync();
}
and
private:
System::Void ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e) {
int Value = e->ProgressPercentage;
this->pipeServer->WaitForConnection(); this->pipeServer->Write(msgOut, 0, msgOut->GetLength(0));
...
}
In the background worker thread:
void Form1::TestCycle( BackgroundWorker^ bw, int SubSysID )
{
array<byte> ^inMsg = (gcnew array<byte>(256));
unsigned msg_cnt = 0;
int len;
System::IO::Pipes::NamedPipeClientStream ^pipeClient =
gcnew NamedPipeClientStream(".", "pipeStream1", PipeDirection::In);
pipeClient->Connect(); bw->ReportProgress(0, msg_cnt++);
while (!bw->CancellationPending)
{
len = pipeClient->Read(inMsg, 0, inMsg->GetLength(0));
....
System::Threading::Thread::Sleep(2000); bw->ReportProgress(0, msg_cnt++);
}
}
So the order of execution is:
1) Form1 loads, creates the NamedPipe, starts the background worker TestCycle
2) TestCycle sends a ProgressReport then blocks on NamedPipe Read()
3) Form1::ProgressChanged() gets the report, writes it to TextBox then Writes to NamedPipe.
4) TestCycle NamedPipe Read() returns, so he sleeps awhile then goes to step 2.
The first ProgressReport from TestCycle startup code shows up in Form1::TextBox.
Then the first pipeClient->Read completes, and the second ProgressReport is displayed.
But just after that, I get:
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
Additional information: Exception has been thrown by the target of an invocation.
Can anyone tell me what's going wrong, or even how to find what's going wrong?