TargetException on Invoke - c#

I have a problem with my Invoke() throwing a TargetException.
public Controller(SystemUI ui, System system)
{
UI = ui;
System = system;
UI.CommandEntered += ParseCommand;
Commands = new Dictionary<string, Delegate>();
Commands.Add(":q", new Action(UI.Close));
}
I then call Commands[input[0]].Method.Invoke(this, input.ToArray<object>());, but it throws a TargetException with the message
Object does not match target type.
Do I need a cast?
I'm quite lost, and I'd appreciate any help!

Based on comments above, you are trying to invoke an Action (UI.Close), but you are passing an array of objects as parameters to this action, which has no parameters therefore incurring this exception.
Change...
input.toArray<object>()
to...
new object[0], or new object[] {} // or perhaps even just null may do the trick.

Related

control.invoke with an out parameter

Winforms, C#, VS2010.
I have a polling thread that runs for the lifetime of my app.
Occasionally it calls an event on my main form. I've not touched the code for years and it's run successfully but now I need to add an "out" parameter to the list of parameters. I've searched online but all the threads I've found have been regarding reflection and been complex to attempt to convert to my context. Mine doesn't use reflection.
Can somebody help over how to fix this pls? On the reflection threads I read people seem to check some object array for the out parameter result, which I don't use in my code, and I wouldn't know where to get it anyway.
private bool OnNeedUpdateCreateEvent(string title, string message,
bool creatingNew, out string newPlanName)
{
newPlanName = "";
// 1st pass through this function.
// Check to see if this is being called from another thread rather
// than the main thread. If so then invoke is required
if (InvokeRequired)
{
// Invoke and recall this method.
return (bool)Invoke(new onNeedToUpdatePlanEvent(OnNeedUpdateCreateEvent),
title, message, creatingNew, out newPlanName); <- wrong out param
}
else
{
// 2nd pass through this function due to invoke, or invoke not required
return InputDlg(this, title, message, creatingNew, out newPlanName);
}
}
It is much like you already know, you just haven't found the array yet. It is automatically created by the compiler. The signature of the Invoke method is:
public object Invoke(
Delegate method,
params object[] args
)
It is the params keyword that gets the compiler to auto-create the array. Nice syntax sugar, but it doesn't help you here. You just have to do it yourself, like this:
if (!creatingNew) {
// Invoke and recall this method.
object[] args = new object[] { title, message, creatingNew, null };
var retval = (bool)Invoke(new onNeedToUpdatePlanEvent(OnNeedUpdateCreateEvent), args);
newPlanName = (string)args[3];
return retval;
}
// etc..

In TPL Dataflow, is it possible to change DataflowBlockOptions after block is created but before it is used?

... and have it take effect?
I'd like to defer setting the ExecutionDataflowBlockOptions.SingleProducerConstrained property until I'm ready to link the network together. (Because, I want to separate creating the blocks, with their semantics, from linking the network together, with its semantics.)
But as far as I can tell you can only set the ExecutionDataflowBlockOptions when the block is created (e.g., for TransformBlock, TransformManyBlock, etc, you pass it in to the constructor and it is not visible otherwise).
However ... it hasn't escaped my notice that the properties have public setters. So ... can I create the block with a placeholder instance of ExecutionDataflowBlockOptions and hold on to it so that I can later set SingleProducerConstrained=true if I desire, when linking the blocks together (and that it will take effect)?
(BTW, is there any way to tell if SingleProducerConstrained is having any effect other than measuring throughput?)
Update: #i3amon correctly pointed out in his answer this can't be done because dataflow blocks clone the DataflowBlockOptions you pass in and use that. But I did it anyway, using internal data structures I can access via reflection and dynamic. I put that in an answer below.
It isn't possible. Modifying the options after the fact won't work. The options are cloned inside the block's constructor. Changing the options later will have no effect.
You can see examples of that here and here and it's simple to verify:
var options = new ExecutionDataflowBlockOptions
{
NameFormat = "bar",
};
var block = new ActionBlock<int>(_ => { }, options);
options.NameFormat = "hamster";
Console.WriteLine(block.ToString());
Output:
bar
Let me answer my own question. Using information from DotNetInside's decompile of the Dataflow assembly, for example, TransformBlock here (thanks #i3amon again for the link to dotnetinside.com), and the very nice ExposedObject package at codeplex here (which I learned about at this blog post, I did the following:
The TPL Dataflow blocks all implement debugger visualizers via the DebuggerTypeProxy attribute, which, applied to a type, names another type to use in the Visual Studio debugger whenever the original type is to be displayed (e.g., watch window).
Each of these DebuggerTypeProxy-named classes are inner classes of the dataflow block the attribute is attached to, usually named DebugView. That class is always private and sealed. It exposes lots of cool stuff about the dataflow block, including its genuine (not a copy) DataflowBlockOptions and also - if the block is a source block - an ITargetBlock[], which can be used to trace the dataflow network from its start block after construction.
Once you get an instance of the DebugView you can use dynamic via ExposedObject to get any of the properties exposed by the class - ExposedObject lets you take an object and use ordinary method and property syntax to access its methods and properties.
Thus you can get the DataflowBlockOptions out of the dataflow block and change its NameFormat, and if it is an ExecutionDataflowBlockOptions (and you haven't yet hooked up the block to other blocks) you can change its SingleProducerConstrained value.
However you can't use dynamic to find or construct the instance of the inner DebugView class. You need reflection for that. You start by getting the DebuggerTypeProxy attribute off your
dataflow block's type, fetch the name of the debugging class, assume it is an inner class of
the dataflow block's type and search for it, convert it to a closed generic type, and finally
construct an instance.
Be fully aware that you're using undocumented code from the dataflow internals. Use your own
judgement about whether this is a good idea. In my opinion, the developers of TPL Dataflow did a lot of work to support viewing these blocks in the debugger, and they'll probably keep it up. Details may change, but, if you're doing proper error checking on your reflection and dynamic use of these types, you will be able to discover when your code stops working with a new version of TPL Dataflow.
The following code fragments probably don't compile together - they're simply cut&pasted out of my working code, from different classes, but they certainly give you the idea. I made it work fine. (Also, for brevity, I elided all error checking.) (Also, I developed/tested this code with version 4.5.20.0 only of TPL dataflow, so you may have to adapt it for past - or future! - versions.)
// Set (change) the NameFormat of a dataflow block after construction
public void SetNameFormat(IDataflowBlock block, string nameFormat)
{
try
{
dynamic debugView = block.GetInternalData(Logger);
if (null != debugView)
{
var blockOptions = debugView.DataflowBlockOptions as DataflowBlockOptions;
blockOptions.NameFormat = nameFormat;
}
}
catch (Exception ex)
{
...
}
}
// Get access to the internal data of a dataflow block via its DebugTypeProxy class
public static dynamic GetInternalData(this IDataflowBlock block)
{
Type blockType = block.GetType();
try
{
// Get the DebuggerTypeProxy attribute, which names the debug class type.
DebuggerTypeProxyAttribute debuggerTypeProxyAttr =
blockType.GetCustomAttributes(true).OfType<DebuggerTypeProxyAttribute>().Single();
// Get the name of the debug class type
string debuggerTypeProxyNestedClassName =
GetNestedTypeNameFromTypeProxyName(debuggerTypeProxyAttr.ProxyTypeName);
// Get the actual Type of the nested class type (it will be open generic)
Type openDebuggerTypeProxyNestedClass = blockType.GetNestedType(
debuggerTypeProxyNestedClassName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
// Close it with the actual type arguments from the outer (dataflow block) Type.
Type debuggerTypeProxyNestedClass =
openDebuggerTypeProxyNestedClass.CloseNestedTypeOfClosedGeneric(blockType);
// Now create an instance of the debug class directed at the given dataflow block.
dynamic debugView = ExposedObject.New(debuggerTypeProxyNestedClass, block);
return debugView;
}
catch (Exception ex)
{
...
return null;
}
}
// Given a (Type of a) (open) inner class of a generic class, return the (Type
// of the) closed inner class.
public static Type CloseNestedTypeOfClosedGeneric(
this Type openNestedType,
Type closedOuterGenericType)
{
Type[] outerGenericTypeArguments = closedOuterGenericType.GetGenericArguments();
Type closedNestedType = openNestedType.MakeGenericType(outerGenericTypeArguments);
return closedNestedType;
}
// A cheesy helper to pull a type name for a nested type out of a full assembly name.
private static string GetNestedTypeNameFromTypeProxyName(string value)
{
// Expecting it to have the following form: full assembly name, e.g.,
// "System.Threading...FooBlock`1+NESTEDNAMEHERE, System..."
Match m = Regex.Match(value, #"^.*`\d+[+]([_\w-[0-9]][_\w]+),.*$", RegexOptions.IgnoreCase);
if (!m.Success)
return null;
else
return m.Groups[1].Value;
}
// Added to IgorO.ExposedObjectProject.ExposedObject class to let me construct an
// object using a constructor with an argument.
public ExposedObject {
...
public static dynamic New(Type type, object arg)
{
return new ExposedObject(Create(type, arg));
}
private static object Create(Type type, object arg)
{
// Create instance using Activator
object res = Activator.CreateInstance(type, arg);
return res;
// ... or, alternatively, this works using reflection, your choice:
Type argType = arg.GetType();
ConstructorInfo constructorInfo = GetConstructorInfo(type, argType);
return constructorInfo.Invoke(new object[] { arg });
}
...
}

WPF C# Threading

I am writing a code in c# to do image processing. I want to use threading and i suppose threading in WPF application is little different. I tried to run thread but it only works when the function is void(), i.e does not take any arguments.
However, my function is taking 3 arguemnts like this
frame_extract.Frame_Processing(_colorFrame_, widht, height);
So therefore the following does not work
depth_Threads = new System.Threading.Thread(**) since ** takes on void() type.
perhaps i am missing something, but my question is how can i work with threading for functions that take arguments.
Maybe you could use the TPL.
It should then be something like:
Task.Factory.StartNew(() => frame_extract.Frame_Processing(_colorFrame_, widht, height));
But be aware that you might have to marshal to the ui-thread.
If you want to create the thread in the ui thread and want the new thread to interact with mentioned ui thread, something like the following should work:
var task = new Task(() => frame_extract.Frame_Processing(_colorFrame_, widht, height));
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
That should work.
I'm not 100% sure if that's what you want, but I think you need to do this :
depth_Threads = new System.Threading.Thread(()=>frame_extract.Frame_Processing(_colorFrame_, widht, height));
It depends on what values you are passing in. Sometimes if you are using objects, they are locked to a given thread in which case you need to create duplicates prior and then pass the duplicates into the new thread.
Do the following. Your method should receive single object argument like this void SomeVoid(object obj). Make an object array with all variables that you want to pass to the method SomeVoid like this object[] objArr = { arg1, arg2, arg3 }; and then call the Start method of thread object with objArr argument since the Start() method receives one object parameter. Now back to your method, cast and obj received from Start method to an object array like this object arr = obj as object[]; and then you can access those 3 arguments like this arr[0] arr[1] and arr[2]
You can use the ParameterizedThreadStart class.
1) Create a class who will holds your three arguments
public class FrameProcessingArguments
{
public object ColorFrame { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
2) Modify your Frame_Processing method to take as parameter an instance of Object and inside it, cast that instance as a FrameProcessingArguments
if (arguments == null) throw new NullArgumentException();
if(arguments.GetType() != typeof(FrameProcessingArguments)) throw new InvalidTypeException();
FrameProcessingArguments _arguments = (FrameProcessingArguments) arguments;
3) Create and start your thread
FrameProcessingArguments arguments = new FrameProcessingArguments()
{
ColorFrame = null,
Width = 800,
Height = 600
}
Thread thread = new Thread (new ParameterizedThreadStart(frame_extract.Frame_Processing));
// You can also let the compiler infers the appropriate delegate creation syntax:
// and use the short form : Thread thread = new Thread(frame_extract.Frame_Processing);
thread.Start (arguments);

Delegate in method using variables in scope of method but outside delegate scope

I wrote some sample code where I have an Action delegate declared in a method body where two params are passed and then consumed by the delegate code without those params being passed into the delagte. It seems cleaner to me to explictely pass in these params to the delegate too, but in this case I am not, and this code would work fine.
I am wondering how .NET keeps these references available in the export delegate that is now running on a new thread.
public void MyMethod(string name, ComplexObject myObj)
{
Action export = () => {
//do something with name
name = name + name;
//do something with complex reference object
myObj.SomeMethod(name);
};
// do more work
// example launch export on a new thread
System.Threading.Thread newThread = new System.Threading.Thread(new System.Threading.ThreadStart(export));
newThread.Start();
}
The compiler creates a special type that keeps those variables. Then, instead of storing those variables on the stack, it instantiates an instance of that type every time you call that method. Then, the anonymous delegates use a reference to that new instance to get access to those variables.

C# parameter count mismatch when trying to add AsyncCallback into BeginInvoke()

I have main form (PrenosForm) and I am trying to run Form2 asynchronously.
It works without callback delegate:
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, null); //works 1.
Doesn't work with callback delegate (parameter count mismatch):
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, new AsyncCallback(callBackDelegate), null); //doesn't work parameter count mismatch 2.
Works with callback delegate if I do it like this:
cp.BeginInvoke(datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt, new AsyncCallback(callBackDelegate), null); //works 3.
My question is why does one way work and the other doesn't? I'm new at this. Would anyone be so kind as to answer my question and point out my mistakes?
private delegate void copyDelegat(List<ListViewItem> datoteke, string path, PrenosForm forma, DragDropEffects efekt);
private delegate void callBackDelegat(IAsyncResult a);
public void doCopy(List<ListViewItem> datoteke, string path, PrenosForm forma, DragDropEffects efekt)
{
new Form2(datoteke, path, forma, efekt);
}
public void callBackFunc(IAsyncResult a)
{
AsyncResult res = a.AsyncState as AsyncResult;
copyDelegat delegat = res.AsyncDelegate as copyDelegat;
delegat.EndInvoke(a);
}
public void kopiraj(List<ListViewItem> datoteke, DragDropEffects efekt)
{
copyDelegat cp = new copyDelegat(doCopy);
callBackDelegat callBackDelegate = new callBackDelegat(callBackFunc);
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, new AsyncCallback(callBackDelegate), null); //doesn't work parameter count missmatch 2.
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, null); //works 1.
cp.BeginInvoke(datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt, new AsyncCallback(callBackDelegate), null); //works 3.
}
It is because Control.BeginInvoke() has a completely different signature from SomeDelegate.BeginInvoke(). While their method names are the same, they are fundamentally different methods. And fundamentally work differently at runtime, there is no comparison.
Control.BeginInvoke() takes a delegate and an object[]. Cast in stone.
private delegate SomeDelegate(mumble, foo, bar) automatically creates a SomeDelegate.BeginInvoke() method. Whose signature takes those three arguments, plus two extra arguments, a callback and a state object.
A significant runtime difference is that Control.BeginInvoke() can call a delegate and if it bombs with an exception then the exception is raised on the UI thread. A delegate's BeginInvoke() method doesn't do this, it re-raises the exception in the callback that calls EndInvoke().
Very confuzzling, I know, maybe they shouldn't have used the same name.
Don't do this at all.
Showing multiple forms on different threads is an extremely bad idea and will end up causing lots of trouble.
Your second example doesn't work because Control.BeginInvoke doesn't support a callback parameter.
Your code is interpreted as calling a delegate with three parameters; an array, and AsyncCallback, and null.
Since your method doesn't take such parameters, an exception is thrown.
Also, calling Control.BeginInvoke won't run a function in the background; it will run it on the UI thread when it next reaches the message loop.

Categories

Resources