Very strange behaviour, can't cast to Object!

G

Gotch@

Hi,
I'm getting a very strange behaviour while running a project I've
done.... Let's expose it: I've two projects. Both of them use a Form
to do some Gui stuff. Other threads pack up messages this way like:

public class UiMsg
{
public enum MsgType { StatusOk };

public MsgType Type;
public Object args;
}

this for the first, while the second:

public class UIData{

public enum dataType{msgSendError, netWorkStatus,
msgFromOp, okClose};

public Object content;
public dataType type;

}

And that's very similar... Then I use the usual Invoke, passing it a
delegate function and an Object Array like:

Object o = (Object)ums;
Invoke(FormCall, new Object[]{ o });

this in the first, where ums is a UiMsg, while in the second

Object []args=new Object[1];

args[0]=(Object)udata;

Invoke(uiUp,args);

.... again pretty similar... Well both compile fine, but when they run
THE FIRST casts out an ArgumentException, complaing that "Object of
type 'ServerApp.UIManager+UiMsg' cannot be converted to type
'System.Object[]'."

..... strange enough... isn't it??? And more strange is the fact that
it says +UiMsg... why it doesn't use the point?!?! What's wrong, did I
forgot checking something??? I tried lot of thing, even making the
codes identical... but no way still the same.

Plase help me solve this mistery...
 
M

Marc Gravell

The + is just the runtime name of the nested class; ignore it...

The problem is not that it can't cast to object, but that it cant cast
to an array-of-object (object[]).

Do you perhaps have the method declared with a "params" array? If this
is the case, then although via C# you can use:

FormCall(singleValue);

behind the scenes, this is actually FormCall(new object[]
{singleValue});

i.e. the arg must be in an object-array. This is a common gotcha when
using reflection. In this case, the args (to Invoke[]) must be an
array, and the corresponding element must *itself* be an array - i.e.
object[] args = {new object[] {value}};

any use?

Marc
 
G

Gotch@

I'm not sure to understand you at all.... Well I know it cannot cast
to an array of objects... but in a case (the second one) it works
fine, in the first it doesn't really work, even if the code is very
similar. I'm pasting the function pointed by the form delegate:

private void updateMyForm(Object []args)
{
UIManager.UiMsg ums=(UIManager.UiMsg)args[0];

switch (ums.Type)
{
case UIManager.UiMsg.MsgType.StatusOk:

systemStatusString = "Sistema OK";
updateStatusLabel();

break;

}

}

As you can see it's pretty standard... Anyway I tried to look out for
FormCall... but it's undocumented... it's also very rare in Google (I
only found a reference in VB)...

Anyway, is there a particular reason for Invoke isn't good??? I just
want to UNDERSTAND the difference between the two situations. I'm
attaching the functions that call the delegate too:

public void sendMsgToUi(UIManager.UiMsg ums){

Object o = (Object)ums;

Monitor.Enter(formLock);
if (ifUp == false)
Monitor.Wait(formLock);
Monitor.Exit(formLock);

Invoke(FormCall, new Object[]{ o });

}


it's strange I think I'm missing some simple point... Think also that
I'm running both the forms simultaneously... but from different
threads... May this be a problem??
 
P

Peter Duniho

Gotch@ said:
I'm not sure to understand you at all.... Well I know it cannot cast
to an array of objects... but in a case (the second one) it works
fine, in the first it doesn't really work, even if the code is very
similar. I'm pasting the function pointed by the form delegate:

private void updateMyForm(Object []args)

There's your problem right there. And it's just what Marc said it was.

The delegate method updateMyForm (that is, the method assigned to the
delegate variable) takes an object[] parameter ("args"), but you are
passing it a UiMsg instance.

And again, to fix it you need to do just as Marc suggested. Instead of:

Invoke(FormCall, new Object[]{ o });

You need:

Invoke(FormCall, new Object[]{ new object[] { o } })

Actually, there's no need for the "o" variable, since "ums" is already
an object instance (everything inherits object). So you really could
just write:

Invoke(FormCall, new Object[]{ new object[] { ums } });

While I don't recommend creating forms from more than one thread, it's
not necessarily a problem and for sure it has nothing to do with this
issue. This is a straight-forward issue of you failing to provide the
correct type for the parameter to the method.

As for the difference from the second example you posted, well...since
you didn't post complete code, it's difficult to say for sure. But it's
pretty obvious that if it works, you are passing the correct type for
the parameter and so obviously the delegate method being called is not
exactly the same or the way in which you are calling it is not exactly
the same.

Pete
 
G

Gotch@

Thanks a lot, I put in the

Invoke(FormCall, new Object[]{ new object[] { o } })

and everything works fine. But now, sorry if I bore you, but I code in
C# just from 3 months and I'm curious, I'd like to understand better
the thing... Becuase the form:


Object []{ new object[]{ o }} remembered me very much like I was
doing an Object array with only one element and that element was
another Object array. I think that this comes from my C++ background,
where it would have taken just a simple (Object [] ) cast.... C#
syntax not very clear to me in these corners yet...
 
J

Jon Skeet [C# MVP]

Gotch@ said:
Thanks a lot, I put in the

Invoke(FormCall, new Object[]{ new object[] { o } })

and everything works fine. But now, sorry if I bore you, but I code in
C# just from 3 months and I'm curious, I'd like to understand better
the thing... Becuase the form:


Object []{ new object[]{ o }} remembered me very much like I was
doing an Object array with only one element and that element was
another Object array. I think that this comes from my C++ background,
where it would have taken just a simple (Object [] ) cast.... C#
syntax not very clear to me in these corners yet...

That's exactly what it's doing - it's creating an object array wrapped
in another object array. The outer object array represents *all* the
arguments to the delegate. You've got one argument, which you want to
be an object array in itself.
 

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