Calling methods by reflection invoke and [STAThread]

F

Fruber Malcome

After some additional research into my previously mentioned problem about
Clipboard.SetDataObject.
I found that the handler I am calling that calls this function is derived
from reflection.

I do this because I have an array of buttons etc on a commandbar, I then
have an onAction property of this array of commandbar buttons, when I create
each button I keep them in an array of custom button classes that contain
this string which is really the name of the function handler.

So I wrap all clicks in the following function: - if I call
Clipboard.SetDataObject in any of my button handlers, I get the mentioned
exception that states that I need to ensure my main function has the
STAThread attribute. Is there a better way to perform this type of task?
(without creating the buttons design time and/or making them members of the
class as button objects and then maually adding the events)
How can I get rid of this exception.


private void _onButtonClick( Office.CommandBarButton btn, ref bool
bHandled )
{
string strMessage = "";
try
{
if ( btn.OnAction == null || bHandled == true )
return;
bHandled = true;
Type type = this.GetType();
MethodInfo mi = type.GetMethod( btn.OnAction, (BindingFlags.Instance
| BindingFlags.NonPublic | BindingFlags.Public) );
if ( mi != null )
mi.Invoke( this, new object[]{} );
else
{
strMessage = String.Format( "Control:\t{0}\nFunc:\t{1}\n",
btn.Tag, btn.OnAction );
_showMessage( strMessage, Types.MSG_APP_UNLISTED_FUNC );
}
}
catch( COMException e )
{
showCOMException( e );
}
catch( Exception e )
{
showException( e );
}
}
 
F

Fruber Malcome

It's seems I've answered this question through some testing, but have not
solved my problem.

It seems the Method.Invoke is not the problem, if I remove that code and
just manually call the function, I still get the STAThread exception.

For some additional information, in case it wasn't apparent:

The _onButtonClick function is a delegate to handle all commandbar / menubar
events.
So each button has: btn.Click += _menuClickEvent;
the _menuClickEvent is a new Office._CommandBarEvents_ClickEventHandler(
_onButtonClick );

thanks - bill
 
F

Fruber Malcome

As an additional note, I've tried:
Thread.CurrentThread.ApartmentState = ApartmentState.STA;

in the _onButtonClick function and after setting this and viewing the
property - it's still set at MTA.
Any way to change this?

thanks - bill


Fruber Malcome said:
It's seems I've answered this question through some testing, but have not
solved my problem.

It seems the Method.Invoke is not the problem, if I remove that code and
just manually call the function, I still get the STAThread exception.

For some additional information, in case it wasn't apparent:

The _onButtonClick function is a delegate to handle all commandbar /
menubar events.
So each button has: btn.Click += _menuClickEvent;
the _menuClickEvent is a new Office._CommandBarEvents_ClickEventHandler(
_onButtonClick );

thanks - bill



Fruber Malcome said:
After some additional research into my previously mentioned problem about
Clipboard.SetDataObject.
I found that the handler I am calling that calls this function is derived
from reflection.

I do this because I have an array of buttons etc on a commandbar, I then
have an onAction property of this array of commandbar buttons, when I
create each button I keep them in an array of custom button classes that
contain this string which is really the name of the function handler.

So I wrap all clicks in the following function: - if I call
Clipboard.SetDataObject in any of my button handlers, I get the mentioned
exception that states that I need to ensure my main function has the
STAThread attribute. Is there a better way to perform this type of task?
(without creating the buttons design time and/or making them members of
the class as button objects and then maually adding the events)
How can I get rid of this exception.


private void _onButtonClick( Office.CommandBarButton btn, ref bool
bHandled )
{
string strMessage = "";
try
{
if ( btn.OnAction == null || bHandled == true )
return;
bHandled = true;
Type type = this.GetType();
MethodInfo mi = type.GetMethod( btn.OnAction,
(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) );
if ( mi != null )
mi.Invoke( this, new object[]{} );
else
{
strMessage = String.Format( "Control:\t{0}\nFunc:\t{1}\n",
btn.Tag, btn.OnAction );
_showMessage( strMessage, Types.MSG_APP_UNLISTED_FUNC );
}
}
catch( COMException e )
{
showCOMException( e );
}
catch( Exception e )
{
showException( e );
}
}
 
F

Fruber Malcome

I finally solved this problem by using a thread wrapper class around my most
common STA necessary functions.
Since I made them static, I can then call these functions - passing whatever
data I want - and then my wrapper/helper class creates a new thread, sets
the apartment to STA, then performs the task and then returns.

This solves all of my STA related problems, and still keeps the normal code
easy to read.
(only my helper class is a little complex - but at least all that code is
centralized.)

If anyone has this same problem and is curious how it is implemented, I'll
be more than happy to share the class.

thanks - Fruber.
 

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