Recurse into a function without referring to function name - c#

I have numerous functions that are called from a background thread, but then need to perform a GUI operation. Therefore in each function, I switch context to the GUI thread. However I'm wondering if my code can be improved?
Here's a cut down example of how my code typically looks now:
public void FunctionABC(string test)
{
// Make sure we are in the GUI thread.
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => FunctionABC(test))); return;
}
// main body of function
}
The main part I have a problem with is having to mention my own function name explicitly in the context switch (I partly dislike this because I keep forgetting to change the name when I copy and paste the code!)
Any ideas for a more generic way of switching context, e.g. is any way of calling back into my own function via some clever pointer that avoids naming the function explicitly?
Something like this snippet would be good (which doesn't build however):
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => this(test))); return;
Thoughts?

How about pulling the dispatch code into a separate method?
public void Dispatch(Action action)
{
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
else
{
action();
}
}
and:
Dispatch(() => FunctionABC(test));

You can take this reusable method:
private void ExecuteOnDispatcherThread(Action action)
{
if (!this.Dispatcher.CheckAccess()) {
this.Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
else {
action();
}
}
And invoke it like this:
this.ExecuteOnDispatcherThread(() => FunctionABC(test));

Related

C# delegates and why do we need them?

I am trying to understand "callback pattern". Every answer says that this is done with delegates (which I know them). But the codes on the answers are something like that:
public delegate void Callback(string result);
public void Test()
{
CallBack callback = CallbackFunction;
DoWork(callback);
}
public void DoWork(CallBack callback)
{
callback("Hello world");
}
public void CallbackFunction(string result)
{
Console.WriteLine(result);
}
I really don't understand, why we need delegate for this? We can do this in this way too?
public void Test()
{
DoWork();
}
public void DoWork()
{
CallbackFunction("Hello world");
}
public void CallbackFunction(string result)
{
Console.WriteLine(result);
}
Besides that, for example in Java, a callback means a real "return" to the main program's "particular function" after an event. But when we use delegates, isn't this just calling another method?
How can we make a callback that finally calls an OnFail() method on fail, and OnSuccess() method on success. I am really confused. Can somebody help me to understand this?
A delegate safely encapsulates a method, a kind of a template to a function in its signature. Sometimes it is easy to think it is a pointer to a function.
In your sample, the CallbackFunction can be setted to Callback because both in its definition takes just a string argument.
You could use Action and Func instead of delegate. The difference between them is that an Action does not return something and Func does. For sample:
public void Test(Action success, Action<Exception> error)
{
try
{
// perform some task
success();
}
catch (Exception ex)
{
error(ex);
}
}
And use it:
Test(() => { Console.WriteLine("Success"); },
(ex) => { Console.WriteLine($"Error: {ex.Message}"); });
the generic option of an Action is the type of the arguments you can pas to this method. On the sample, Exception is a argument which is passed to error Action. The same is valid for a Func<> but the last type of a Func is the result type.
Why do we need delegates?
Because in many programs, you need the ability to abstract the concept of a method. One reason is events, another is a set of methods like this:
public void DoWork(Action completeCallback)
{
... //Do Stuff
completeCallback();
}
public void FirstMainMethod()
{
DoWork(() => Console.WriteLine("First callback");
}
public void SecondMainMethod()
{
DoWork(() => Console.WriteLine("Second callback");
}
In other words, different parts of my code need to have a different method run on completion, so I pass it in (I can't use a direct call). The delegate abstraction allows this. Also note that the idea of a "completion" callback in .NET is pretty silly, you almost never need it. You will use delegates for this general idea all the time though.
How can we make a callback that finally calls an OnFail() method on fail, and OnSuccess() method on success?
You can do this pretty easily. You can even make a somewhat generic one (not sure if you would ever want to mind you, but the following code works):
public void SuccessFailHelper(Func<bool> work, Action success, Action failure)
{
if (work())
success();
else
failure();
}

Method or Extension Method to Handle InvokeRequired

I can't quite come up with the solution to creating a generic method to handle the InvokeRequired for void methods (I'll deal with return values later). I was thinking something like:
// Probably not the best name, any ideas? :)
public static void CheckInvoke(this Control instance,
,Action<object, object> action)
{
if (instance.InvokeRequired)
{
instance.Invoke(new MethodInvoker(() => action));
}
else
{
action()
}
}
Then I could write something like:
public partial class MyForm : Form
{
private ThreadedClass c = new ThreadedClass();
public MyForm()
{
c.ThreadedEvent += this.CheckInvoke(this
,this.MethodRequiresInvoke
,sender
,e);
}
}
This doesn't compile obviously, I just can't quite tie it together.
Hans is correct, in that you probably don't want to wrap code like this up, especially since it can cause some debugging issues down the road in determining what thread actions are happening on. That said, this would be the signature you'd want:
public static class FormsExt
{
public static void UnwiseInvoke(this Control instance, Action toDo)
{
if(instance.InvokeRequired)
{
instance.Invoke(toDo);
}
else
{
toDo();
}
}
}
Loose Action parameters of "object,object" (as JerKimball suggests), name it SafeInvoke, and attach to event via anonymous delegate:
c.ThreadedEvent += delegate
{
c.SafeInvoke(this.MethodRequiresInvoke);
};

Creating a class with thread safe functions using InvokeRequired property and Invoke method

I have a class that I created and in the class I do some multi-threading. Usually to do my multi-threading on a form I would use the following method...
//Thread Safe Functions
delegate void Thread_Safe_SendMessage_Progress_Callback(string sProgress);
private void Thread_Safe_SendMessage_Progress(string sProgress)
{
if (this.InvokeRequired)
{
Thread_Safe_SendMessage_Progress_Callback d =
new Thread_Safe_SendMessage_Progress_Callback(Thread_Safe_SendMessage_Progress);
try
{
this.Invoke(d, new object[] { sProgress });
}
catch
{
//ObjectDisposedException
}
}
else
{
//Fire up the thread event
SendMessageThread_Progress(sProgress);
}
}
Now that works perfect! At this point I try to bring the multi-threading into a class i made. When I do that everything seems to be great with the exception of the InvokeRequired property and the Invoke method do not exist within my class. So using this.InvokeRequired throws an error... To give my class that property I do this... (Note that m_iThreadID is set in the constructor and when the thread is created to start with)
private bool InvokeRequired
{
get
{
//Get the current thread id
int iThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
//Compare and return results
return (iThreadID != m_iThreadID);
}
}
Now the only thing left is the Invoke method... How do I get that to work?
Invoke method isn't so "easy" to replicate (side question: why don't you use BeginInvoke? I guess you may don't need to raise the event synchronously). You can get the first form in Application.OpenForms (copy before use!) and inspect that to check for InvokeRequired and BeginInvoke/Invoke.

Invoking method on thread which created object

Let's say I created an object O on the thread T. How can I get, from inside object O the thread T and invoke a method on that thread?. This way, it won't be necessary for the form that created the object to to this:
private void ChangeProgress(int value)
{
progressBar1.Value = value;
}
void FD_ProgressChanged(object sender, DownloadEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<int>(ChangeProgress), new object[] { e.PercentDone });
}
else ChangeProgress(e.PercentDone);
}
which is just ugly and requires whoever uses the object to either figure out which events are raised on the same thread that created the object and which are not and add the if(InvokeRequired)...else code on the ones that are not, or just add the code on every single event handler. I think it would be more elegant if the object itself takes care of invoking the event on the right thread. Is this possible?
Use the BackgroundWorker class. It takes care of all this. Note the ReportProgress event.
You are going to have to track it yourself like
class Foo {
private readonly Thread creatingThread;
public Foo() {
this.creatingThread = Thread.CurrentThread;
}
}
If you don't do that, there is no way to know. But the fact that you are doing this is a smell. Consider using a BackgroundWorker.
There are a few thing you need to consider:
You will need to keep a reference in Object O of a thread that it was created in. Probably in a constructor using Thread.Current static property.
That thread will need to have a SynchronizationContext associated with it. (Generally, UI threads have it. And its not easy to create one for a custom thread you created.)
To invoke a method on that thread, you will need to use Send() or Post() methods on that thread's SynchronizationContext.
Found a nice solution at http://www.codeproject.com/KB/threads/invoke_other_way.aspx
And here's is my generic version:
private void RaiseEventAsync(Delegate handler, object e)
{
if (null != handler)
{
List<Delegate> invocationList = handler.GetInvocationList().ToList();
foreach (Delegate singleCast in invocationList)
{
System.ComponentModel.ISynchronizeInvoke syncInvoke =
singleCast.Target as System.ComponentModel.ISynchronizeInvoke;
try
{
if ((null != syncInvoke) && (syncInvoke.InvokeRequired))
syncInvoke.Invoke(singleCast,
new object[] { this, e });
else
singleCast.Method.Invoke(singleCast.Target, new object[] { this, e });
}
catch
{ }
}
}
}
And this is how you would use it:
protected void OnProgressChanged(DownloadEventArgs e)
{
RaiseEventAsync(ProgressChanged, e);
}
This takes care of my problem without needing to use a BackgroundWorker that is not always wanted (like on my case, where I'm subclassing a class that already uses a different threading object).

Performance issues when updating UI without checking InvokeRequired first?

I have gotten a bit lazy(it's sometimes good) and started updating WinForms UI by invoking a callback without checking InvokeRequired first.
Are there a performance issues or considerations that I should be aware of?
private delegate void SetStatusEventHandler(string statusMessage);
private void SetStatus(string statusMessage)
{
Invoke((MethodInvoker) (() =>
{
resultLabel.Text = statusMessage;
}));
// - vs -
if (InvokeRequired)
{
SetStatusEventHandler cb = SetStatus;
Invoke(cb, statusMessage);
}
else
{
resultLabel.Text = statusMessage;
}
}
[EDIT]: Most of times that a method that calls "invoke" will be called at most like say 10~20 times a second with a wide interval inbetween.
[UPDATE] Settled with the following extension method
public static class SmartInvoker
{
public static void InvokeHandler(this Control control, MethodInvoker del)
{
if (control.InvokeRequired)
{
control.Invoke(del);
return;
}
del();
}
}
...
private void SetStatus(string statusMessage)
{
this.InvokeHandler(() => resultLabel.Text = statusMessage);
}
I guess finding out how to manage extension method classes is another topic I need to dig in. Thank you for your help
EDIT: See the comments for debate about the whole posting vs immediately dispatching malarky.
Either way, my answer is actually the same: unless this is happening hugely often unnecessarily (i.e. most of the time you're on the UI thread to start with, and it's attached to something like a mouse movement handler) I wouldn't worry. It certainly makes the code simpler. If this is going to be invoked very often, I'd measure and test more :)
Invoke is faster with an EventHandler or MethodInvoker delegate than with others. I don't know if there's any difference between the two - you may want to check.
You can make this even simpler by writing an extension method, e.g.
public static void InvokeHandler(this Control control, MethodInvoker handler)
{
control.Invoke(handler);
}
Then you can make your code:
private void SetStatus(string statusMessage)
{
this.InvokeHandler(delegate
{
resultLabel.Text = statusMessage;
});
}
or
private void SetStatus(string statusMessage)
{
InvokeHandler(() => resultLabel.Text = statusMessage);
}
That way you don't need to specify the delegate type.
Why not just add an extension method so you don't have to think about it anymore?
public static object SmartInvoke(this Control control, MethodInvoker del) {
if ( control.InvokeRequired ) {
control.Invoke(del);
return;
}
del();
}
Now your code becomes
private void SetStatus(string statusMessage) {
this.SmartInvoke(() => resultLabel.Text = statusMessage);
}
I believe it just prevents an unnecessary post if you're already on the same thread. So if that would be the most common scenario (being on the correct thread), it might cause a small performance hit by not checking, but I dont believe its actually required.

Categories