UI Threads in C++/CLI

N

None

Hello

To get an understanding of UI threads in C++/CLI, I attempted to
duplicate the following C# example:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/winforms06112002.asp

Here is the code:

public ref class Form1 : public System::Windows::Forms::Form
{
...
....
....
....
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
CalcPiDelegate ^calcPi = gcnew CalcPiDelegate(this, &Form1::calcPi);
calcPi->BeginInvoke(1, nullptr, nullptr);

}

private: delegate System::Void CalcPiDelegate(int max);

private: System::Void calcPi(int max)
{
ShowProgress(0, max);

for (int i = 0; i < max; i++)
{
ShowProgress(i, max);
}
}

private: delegate System::Void ShowProgressDelegate(int i, int max);

private: System::Void ShowProgress(int i, int max)
{
if (richTextBox1->InvokeRequired == false)
{

richTextBox1->AppendText(Convert::String(i) +
Environment::NewLine);
progressBar1->Maximum = max;
progressBar1->Value = i;
}
else
{
ShowProgressDelegate ^progDelegate = gcnew
ShowProgressDelegate(this,&Form1::ShowProgress);

cli::array<int> ^args = gcnew cli::array<int>(2);
args[0] = i;
args[1]= max;

BeginInvoke(progDelegate,args);
}
}
};

The BeginInvoke call causes the following exception:

An unhandled exception of type
'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll

Additional information: Parameter count mismatch.

Unfortunately I can not determine why this error occurs. Any help or
hint is greatly appreciated.

Regards
 
M

Marcus Heege

When I first saw your code, I thought you were kidding me, because IMO this
code should not even compile.

cli::array<int> ^args = gcnew cli::array<int>(2);
args[0] = i;
args[1]= max;

BeginInvoke(progDelegate,args);

Notice that cli::array<int> can *not* be casted into a cli::array<Object^>.
If you call

BeginInvoke(progDelegate, gcnew array<Object^>{i, max});

instead of your call, the app will work.

However, there is still an unanswered question:

The code below tries the same, but he doesn't compile because of the invalid
cast:

using namespace System;

void GetArray(cli::array<Object^>^ arrObj)
{
for each (Object^ o in arrObj)
Console::WriteLine(arrObj);
}

int main()
{
GetArray(gcnew array<Object^>{1, 2});
GetArray(gcnew array<int>{1, 2});
}

In contrast to my code, your code (which does the same cast)
a) it compiles and
b) generates code that produces the wrong array with the cast.

My assumtion is, that control.BeginInvoke is handled specially (and wrong).

Marcus


None said:
Hello

To get an understanding of UI threads in C++/CLI, I attempted to duplicate
the following C# example:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/winforms06112002.asp

Here is the code:

public ref class Form1 : public System::Windows::Forms::Form
{
..
...
...
...
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
CalcPiDelegate ^calcPi = gcnew CalcPiDelegate(this, &Form1::calcPi);
calcPi->BeginInvoke(1, nullptr, nullptr);

}

private: delegate System::Void CalcPiDelegate(int max);

private: System::Void calcPi(int max)
{
ShowProgress(0, max);

for (int i = 0; i < max; i++)
{
ShowProgress(i, max);
}
}

private: delegate System::Void ShowProgressDelegate(int i, int max);

private: System::Void ShowProgress(int i, int max)
{
if (richTextBox1->InvokeRequired == false)
{

richTextBox1->AppendText(Convert::String(i) +
Environment::NewLine);
progressBar1->Maximum = max;
progressBar1->Value = i;
}
else
{
ShowProgressDelegate ^progDelegate = gcnew
ShowProgressDelegate(this,&Form1::ShowProgress);

cli::array<int> ^args = gcnew cli::array<int>(2);
args[0] = i;
args[1]= max;

BeginInvoke(progDelegate,args);
}
}
};

The BeginInvoke call causes the following exception:

An unhandled exception of type
'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll

Additional information: Parameter count mismatch.

Unfortunately I can not determine why this error occurs. Any help or hint
is greatly appreciated.

Regards
 
M

Marcus Heege

I have just got a response from the team. There is a simple reason for this
behaviour:

Control::BeginInvoke has a ParamArray. Since array<int> cannot be casted
into array<Object^>, they create a new array<Object^> with one element, a
reference to the array<int> and pass this to the function.

Marcus

Marcus Heege said:
When I first saw your code, I thought you were kidding me, because IMO
this code should not even compile.

The second argument of Control.BeginInvoke is of type
cli::array said:
cli::array<int> ^args = gcnew cli::array<int>(2);
args[0] = i;
args[1]= max;

BeginInvoke(progDelegate,args);

Notice that cli::array<int> can *not* be casted into a
cli::array<Object^>. If you call

BeginInvoke(progDelegate, gcnew array<Object^>{i, max});

instead of your call, the app will work.

However, there is still an unanswered question:

The code below tries the same, but he doesn't compile because of the
invalid cast:

using namespace System;

void GetArray(cli::array<Object^>^ arrObj)
{
for each (Object^ o in arrObj)
Console::WriteLine(arrObj);
}

int main()
{
GetArray(gcnew array<Object^>{1, 2});
GetArray(gcnew array<int>{1, 2});
}

In contrast to my code, your code (which does the same cast)
a) it compiles and
b) generates code that produces the wrong array with the cast.

My assumtion is, that control.BeginInvoke is handled specially (and
wrong).

Marcus


None said:
Hello

To get an understanding of UI threads in C++/CLI, I attempted to
duplicate the following C# example:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/winforms06112002.asp

Here is the code:

public ref class Form1 : public System::Windows::Forms::Form
{
..
...
...
...
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
CalcPiDelegate ^calcPi = gcnew CalcPiDelegate(this, &Form1::calcPi);
calcPi->BeginInvoke(1, nullptr, nullptr);

}

private: delegate System::Void CalcPiDelegate(int max);

private: System::Void calcPi(int max)
{
ShowProgress(0, max);

for (int i = 0; i < max; i++)
{
ShowProgress(i, max);
}
}

private: delegate System::Void ShowProgressDelegate(int i, int max);

private: System::Void ShowProgress(int i, int max)
{
if (richTextBox1->InvokeRequired == false)
{

richTextBox1->AppendText(Convert::String(i) +
Environment::NewLine);
progressBar1->Maximum = max;
progressBar1->Value = i;
}
else
{
ShowProgressDelegate ^progDelegate = gcnew
ShowProgressDelegate(this,&Form1::ShowProgress);

cli::array<int> ^args = gcnew cli::array<int>(2);
args[0] = i;
args[1]= max;

BeginInvoke(progDelegate,args);
}
}
};

The BeginInvoke call causes the following exception:

An unhandled exception of type
'System.Reflection.TargetParameterCountException' occurred in
mscorlib.dll

Additional information: Parameter count mismatch.

Unfortunately I can not determine why this error occurs. Any help or hint
is greatly appreciated.

Regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top