Is it bad form to use a generic callback? - c#

I've got this code (well, something similar).
private delegate void GenericCallback<T>(T Info);
private void DoWork()
{
System.Threading.Thread Worker = new System.Threading.Thread(
delegate()
{
TestMethod(TestMethodCallback<string>);
}
);
Worker.Start();
}
private void TestMethod(GenericCallback<string> Callback)
{
System.Threading.Thread.Sleep(1000);
if(Callback != null)
{
Callback("Complete");
}
}
private void TestMethod(GenericCallback<int> Callback)
{
System.Threading.Thread.Sleep(1000);
if(Callback != null)
{
Callback(25);
}
}
private void TestMethodCallback<T>(T Info)
{
MessageBox.Show(Info.ToString());
}
Which allows me to call different versions of TestMethod based on the type of a parameter, while also allowing me to have a single callback method.
Is this bad form, or an accepted practice?

It looks like you might be looking for the Action delegate type. It's basically what you have here: a generic void-returning delegate type.

Such an established practice, that some of the work has been done for you. Action in this case, and Func should you return a value, are generic delegates, precisely like this. An advantage is, if I saw your signature:
private void TestMethod(GenericCallback<string> Callback)
I have to look up what GenericCallback<string> is. If I saw:
private void TestMethod(Action<string> callback)
I already know.

Totally fine. In this very simple case it might be preferable to specify a string (since your generic type, with no constraints, can only be dealt with as an Object and so ToString() is one of the very few useful things you can call no matter what you pass), but obviously this is example code so there are very many accepted ways to do this. Action<> and Func<> are indeed good built-ins to know about, but they have some drawbacks, such as reduced self-documentation (it can be difficult to tell what a Func is expected to do, other than the obvious "take an integer and return an integer".

Assuming that this would be used for returning data asynchronously (otherwise, why not wait for the return value?), it sounds like you haven't discovered Task Parallel Library. In particular, Task<T> is a more generalized way of acheiving callback-like behaviour.
For instance:
private Task<int> TestMethod()
{
TaskCompletionSource<int> tcs=new TaskCompletionSource<int>();
//do something asynchronous
//when asynchronous job is complete
//tcs.SetResult(25);
return tcs.Task;
}

Related

What's the right way to implement ValueTaskSource.SetCompleted

So we have this class implementing IValueTaskSource This code cannot be written as async-await because there's nothing to await on. We send a message to another running thread and get back a ValueTask that can be awaited by the caller to get the notification that the other thread has finished processing the message. However the other thread is pre-existing and already doing work. It receives the message by a completely other way; processes the message, then needs to tell the threadpool-origin thread that it finished. Thus; IValueTaskSource
There is no stock ValueTaskSource (not getting into whether or not there should be; however in this case a stock version would be of questionable utility). What we actully have looks very much like this:
class Message : IValueTaskSource {
public ValueTask Send()
{
/* how the message is sent is irrelevant */
return new ValueTask(this, 0);
}
private Action<object> continuation;
private object continuationState;
void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short _, ValueTaskSourceOnCompletedFlags __)
{
lock(this) {
if (GetStatus(_) == ValueTaskSourceStatus.Pending)
{
this.continuation = continuation;
this.continuationState = state;
return;
}
continuation(continuationState); /* Suspect */
}
}
public void SetCompleted()
{
lock (this)
{
/* set state completed omitted for brevity */
continuation?.Invoke(continuationState); /* Suspect */
}
}
}
I think I'm doing this wrong. Imagine a large chain of these; it seems like it would build up too much stack. In particular, the lines marked /* Suspect */ are exactly that; and ValueTaskSourceOnCompletionFlags is unused. Although it does have the nicety in that an exception thrown by continuation always goes somewhere; assuming that's even a real issue.
Right now, the code works because there are only three of them and the continuations that use them are very much thread agnostic which thread they are on.
Based on the link to ManualResetValueTaskSource provided by Stephen Cleary and the corresponding source code I was able to produce an answer.
ManualResetValueTaskSourceCore<T> provides a complete implementation of IValueTaskSource<T> and IValueTaskSource<T>. This is currently a case of there's no void implementation so create a void implementation with a dummy type. There's some generalized debate on whether bool or object is the best dummy type but I think it doesn't really matter because member padding of T will force alignment anyway.
So the answer is to forward all the methods.
public ValueTask Send()
{
/* how the message is sent is irrelevant */
return CraeteValueTask();
}
private ManualResetValueTaskSourceCore<object> taskSource;
private ValueTask CreateValueTask() => new ValueTask(this, taskSource.Version);
public ValueTaskSourceStatus GetStatus(short version) => taskSource.GetStatus(version);
public void OnCompleted(Action<object> continuation, object state, short version, ValueTaskSourceOnCompletedFlags flags) => taskSource.OnCompleted(continuation, state, version, flags);
public void SetCompleted() => taskSource.SetResult(null);
In this case each message is in its own object so there's no pooling. Doesn't matter. Calling the existing implementation is so much easier than trying to write down the smallest correct implementation that it's still the better way.
I'm pretty sure if I were pooling value task sources the correct way would be to call Reset() inside CreateValueTask().
Here is an example using the INotifyCompletion interface to get the notification, instead of the heavier IValueTaskSource+ValueTask mechanism. The Message class is amended with just one additional instance field, an Action, and it has become awaitable by exposing a GetAwaiter method. Each Message instance is intended to be awaited only once.
public class Message : INotifyCompletion
{
private static readonly Action _completedSentinel = new(() => { });
private Action _continuation;
public Message GetAwaiter() { return this; }
public bool IsCompleted
=> ReferenceEquals(Volatile.Read(ref _continuation), _completedSentinel);
public void OnCompleted(Action continuation)
{
Action original = Interlocked.CompareExchange(ref _continuation,
continuation, null);
if (original is null) return; // Normal case
if (ReferenceEquals(original, _completedSentinel))
continuation(); // Rare case
else
throw new InvalidOperationException("Double await");
}
public void GetResult() { }
public void SetCompleted()
{
Action continuation = Interlocked.Exchange(ref _continuation,
_completedSentinel);
if (continuation is null) return;
ThreadPool.QueueUserWorkItem(state => ((Action)state).Invoke(), continuation);
}
}
Online demo.
The static _completedSentinel field is used in order to resolve a race condition that might occur, between the thread that awaits and the thread that invokes the SetCompleted method. Normally the await will happen first, but the implementation above will not break if it happens after the SetCompleted, or even if the SetCompleted is invoked between the IsCompleted/OnCompleted calls (these are called by the async/await machinery).

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();
}

How can I use delegates to pass methods in a thread wrapper class?

I'm currently self-teaching myself C# and I'm a bit new at programming so apologies in advance if this is covered in another topic (I tried searching).
I've been trying to make a generic worker / thread class that takes in a method which specifically wraps around a long set of procedural steps. The idea is to be able to pause/resume it a manner similar to setting breakpoints to pause/unpause in Visual Studio. To provide context, I'm mostly working with automation with an ASP.NET and XAML WPF interface (XAML at the moment).
My understanding is that I need to use delegates of some sort but I'm looking for a very simple example in plain English. The examples I found are a completely different scope and I have a hard time following the provided solutions in other contexts.
From other examples on MSDN and Stackoverflow, the "Task" worker class is what I have so far, but I'm a bit at a loss on where to on DoDelegatedMethod and my constructor. What I'm trying to do here is to instantiate a Task object, pass in a delegated method on new instantiation, create a new thread, and marry the passed in method to the thread.
The reason why I want a general "Task" is so I can manage specific methods generically instead of having to write a different "DoWork" method for each instance.
Is this the right approach?
class Task
{
private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
private ManualResetEvent _pauseFlag = new ManualResetEvent(true);
private delegate void MyDelegate();
Thread _thread;
public Task() { }
public Task(MyDelegate d = new MyDelegate(DoStuff)) // ERROR
{
_thread = new Thread(DoDelegatedMethod); // ERROR
}
public void Start()
{
_thread.Start();
}
public void Resume()
{
_pauseFlag.Set(); ;
}
public void Stop()
{
_shutdownFlag.Set();
_pauseFlag.Set();
_thread.Join();
}
private void DoDelegatedMethod(MyDelegate d)
{
do
{
d();
}
while (!_shutdownFlag.WaitOne(0));
}
// This does nothing but spin forever until I force it to stop
public void Spin()
{
do
{
// MessageBox.Show("test");
_pauseFlag.WaitOne(Timeout.Infinite);
}
while (!_shutdownFlag.WaitOne(0));
//MessageBox.Show("thread over");
}
}
new Thread() takes a ThreadStart (or ParameterisedThreadStart) argument, and your DoDelegatedMethod callback doesn't have the right signature for ThreadStart. So you need to write something like this:
ThreadStart method = new ThreadStart(() => DoDelegatedMethod(d));
_thread = new Thread(method);
This creates an anonymous callback (the () => DoDelegatedMethod(d) bit) which when run will call DoDelegatedMethod with the delegate d (which is 'captured' by the anonmyous method). Now you pass this anonymous callback to the Thread constructor, so when the thread runs, it will call the anonymous callback, which will in turn call DoDelegatedMethod(d). Effectively the lambda adapts DoDelegatedMethod to the ThreadStart signature.
Another way to do this would be to change DoDelegatedMethod to take no arguments, and store d as a member field of the Task class which DoDelegateMethod would access.
Also, the reason you get an error on your constructor is that default values can only be of a limited set of types, and delegates aren't one of them (only types that are allowed in attributes, like int, long, string and Type are permitted). Use an overload instead:
public Task() : this(new MyDelegate(DoStuff)) { ... }
public Task(MyDelegate d) { ... }
Note you may still get an error if DoStuff is an instance method of Task -- it's not clear. Personally I think having a default delegate for Task to run is a bit of an odd design, so you may just want to get rid of the default constructor.
Following the discussion in the comments I thought it was worth summarising the suggested revisions to the Task class:
public class Task
{
private readonly Action _action;
// other members as before
// default constructor removed
public Task(Action action)
{
_action = action;
}
public void Start()
{
ThreadStart ts = new ThreadStart(DoDelegatedMethod);
_thread = new Thread(ts);
_thread.Start();
}
private void DoDelegatedMethod()
{
do
{
_action();
}
while (!_shutdownFlag.WaitOne(0));
}
// other members as before
}
And the usage:
Task task = new Task(this.AutomatedTasks);
task.Start();
private void AutomatedTasks() { ... }
You may find good implementation of Task Pool manager here
www.codeproject.com/KB/threads/smartthreadpool.aspx
smartthreadpool allows to send in pool any task,
but you have to add Pause\Start functions to it.
I would model this a List which I would enumerate like you would any other list and use 'yield' at the en of the enumerator.

Is there a shorthand for Form.BeginInvoke?

Quite often in my GUI code, I write something like this:
private void SecondTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (progressBar1.InvokeRequired)
{
progressBar1.BeginInvoke(new ElapsedEventHandler(SecondTimer_Elapsed), new[] {sender, e});
return;
}
//Code goes here
}
Of course, this is necessary if the app is multithreaded, as we need to marshall the thread that originally created the control. The thing is, it can be tedious to write the delegate and put the arguments into an array, and it takes up space in the top of every such event handler. Is there an attribute or something along those lines that will replace this code for you? Basically a label that says "if you're on the wrong thread, call me again on the GUI thread with the same args."
I don't know of anything quite like that, but this would probably be a useful extension method for you:
public static class Extensions
{
public static void Execute(this ISynchronizeInvoke invoker,
MethodInvoker action)
{
if (invoker.InvokeRequired)
{
invoker.BeginInvoke(action);
}
else
{
action();
}
}
}
Now this only works for parameterless delegates, of course... but with lambda expressions that needn't be a problem:
progressBar1.Execute(() => SecondTimer_Elapsed(sender, e));
This has the following advantages:
It's simple to write
You can't go wrong with the signature (you're not relying on late binding)
MethodInvoker is executed slightly more efficiently than other delegates, I believe
If you don't have much code to execute, you can write it inline in the lambda expression
You can tidy this up with extension methods:
// Extension methods.
public static void BeginInvoke(this ISynchronizeInvoke #this, MethodInvoker action) {
if (#this.InvokeRequired) #this.BeginInvoke(action);
else action();
}
public static void BeginInvoke<T1, T2>(this ISynchronizeInvoke #this, Action<T1, T2> action, T1 arg1, T2 arg2) {
if (#this.InvokeRequired) #this.BeginInvoke(action, new object[] { arg1, arg2 });
else action(arg1, arg2);
}
// Code elsewhere.
progressBar1.BeginInvoke(() => SecondTimer_Elapsed(sender, e));
// Or:
progressBar1.BeginInvoke(SecondTimer_Elapsed, sender, e);
Edit: Jon Skeet is correct in saying that using the MethodInvoker delegate is faster. From the MSDN:
A call to an EventHandler or MethodInvoker delegate will be faster than a call to another type of delegate.
Grab an AOP framework for this. You can create an MethodInterceptionAspect that fires when a function is called. Then you can do the checks, and either toss the function (you have a ref to the function and it's arguments) to the GUI thread, or execute it directly.
Advantage is that you will have to write this code once, and can apply it to every property needed with just an attribute.

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