Running Tasks generically - c#

In my project I heavily make use of TPL, and I decide to design a generic way of producing tasks, instead of calling new Task(Action);, new Task(Action<object>, object); or Task.Factory.StartNew(Action) etc. explicitly.
I will have a function like
void SpawnTask<A,B>( Action<A,B> action, A a, B b) { ... }
void SpawnTask<A,B,C>( Action<A,B,C> action, A a, B b, C c) { ... }
for creating and starting tasks.
Also I need to run a mandatory method after each task completed. Thus I have to wrap the actual method I want to run in another method like
void RuncTask(Action action)
{
action();
MandatoryMethod();
}
So far I come up with two different approaches.
First, using anonymous delegates:
void SpawnTask<A,B>(Action<A,B> action, A a, B b)
{
A dummyA = a; // To localize the parameters.
B dummyB = b;
var methodDelegate = delegate { action(dummyA,dummyB); };
var taskDelegate = delegate { RunTask(methodDelegate); };
Task.Factory.StartNew( taskDelegate );
}
void RuncTask(Action action)
{
action();
MandatoryMethod();
}
Second, using tuple:
void SpawnTask<A,B>(Action<A,B> action, A a, B b)
{
Tuple<Action<A,B>, A, B> tpl = Tuple.Create(action, a, b);
Action<object> act = RunTask<A,B>;
Task.Factory.StartNew( act, tpl );
}
void RuncTask<A,B>(object obj)
{
var tpl = (Tuple<Action<A, B>, A, B>)param;
tpl.Item1(tpl.Item2,tpl.Item3);
MandatoryMethod();
}
I like the first one because, it is simpler. The second has casting, requires other generic RunTask methods to be implemented for different number of parameters. But I do not know if creating too much anonymous delegates can cause side effects.
Which one do you prefer? Why? Or what other solutions do you have?

Well, you can always create an extension method on Action<TA,TB> ... and you should use continuations rather than wrapped method calls to implement the behavior of always performing another action when the task completes:
public static class TaskExtensions
{
public static void RunTask<TA,TB>( Action<TA,TB> action, TA a, TB b )
{
Task newTask = new Task( () => action(a,b) );
newTask.ContinueWith( MandatoryMethod );
newTask.Start();
}
// if you need to support other signature (more parameters) you would need to
// create additional overloads of RunTask with more generic parameters...
public static void RunTask( Action action );
public static void RunTask<TA>( Action<TA> action, TA a );
// etc ...
private static void MandatoryMethod( Task t ) { /* your continuation logic */ }
}
Now you can use this code as follows:
public void SomeMethod( int x, int y ) { ... }
// later...
Action<int,int> myAction = SomeMethod;
myAction.RunTask( 1, 2 );
Note that in the above implementation the continuation method (MandatoryMethod) will be executed asynchronously. If you desire synchronous execution (as is implemented in your example), you can use the overload of ContinueWith that takes a TaskContinuationOptions and pass in TaskContinuationOptions.ExecuteSynchronously.

Frankly, I mot quite sure what you are trying to accomplish with that. What advantage over directly using Task constructor or Task.Factory are you hoping to achieve?
As for a "mandatory method" that needs to execute after task finishes, look at continuations (e.g. Task.ContinueWith).

Related

Passing method to be executed asynch

I am creating a Windows forms application which executes a lot of similar operations on a piece of data. All these operations are almost the same so I would like to create a single method that
makes the user interface read-only
sets up messages like "Executing operation1..."
executes the operation asynchronously, so the user interface remains responsive
sets up message to "Operation1 finished."
Set interface read-only to false.
I imagine calling this single method like
ExecuteOperation([method to execute], "Executing operation1")
I am sure that this is simple but I am lost between delegates and tasks so please show me how to write a method that is capable of running a selected method, preferably with multiple parameters and how this method is called.
Note:
By disabling the interface I mean
MainMenu.Enabled = false;
txtData.ReadOnly = true;
You're probably looking for something like this (I've shown an example here for a method that takes parameters, since you asked for that case specifically):
private async Task ExecuteOperation(string operationName, Action action)
{
//Disable UI here
//Set 'Executing' message here
await Task.Run(action);
//Set 'Finished' message here
//Enable UI here
}
private async Task CallOperation()
{
int x, y, z; //These get set to something here...
await ExecuteOperation("Operation1", () => OperationWithParams(x, y, z));
}
You most likely also want to add some exception handling in your ExecuteOperation wrapper if you have standard exceptions that your various operations can throw and which should result in UI feedback of some sort.
On a side note, I reordered the name and the action, as this makes it somewhat cleaner (IMO) to pass an anonymous method as the action.
You can pass methods into methods, so to speak, but the delegates have to match. If you have methods with different signatures, you're angling the wrong way.
The Action and Func delegates are generic. There's one to match almost any signature (up to 16 parameters), but again, they have to match the method signature. If you have one method with one parameter, and another with two, or two with different types of parameters, you can't pass those into the same delegate.
So, really it depends on how similar your methods are. If they have varied types of parameters, you'd probably have to "wrap" these calls.
Simplified example:
void Main()
{
List<Action> actions = new List<Action>
{
() => Method1("myString"),
() => Method2("myString2", "myString3")
};
foreach(var action in actions) InvokeAction(action);
}
void InvokeAction(Action action)
{
action();
}
void Method1(string x)
{
Console.WriteLine(x);
}
void Method2(string y, string z)
{
Console.WriteLine(y);
Console.WriteLine(z);
}
On the other hand, if your methods have the same signature, it's a bit simpler:
void Main()
{
InvokeAction(Method1, "myString");
InvokeAction(Method2, "myString2");
}
void InvokeAction(Action<string> action, string param)
{
action(param);
}
void Method1(string x)
{
Console.WriteLine(x);
}
void Method2(string y)
{
Console.WriteLine(y);
}
Now, as to running that asynchronously, it's as simple as using a System.Threading.Task, if you're on .NET 4.0. You could alter my example method as such:
void InvokeAction(Action<string> action, string param)
{
Task.Factory.StartNew(() => action(param));
}
How about something like this (non async/await - version):
void Foo<T>(Action<T> action, string message)
{
MethodWhichMakesMyInterfaceReadOnlyAndSetsMessage(message);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, arg) => action.Invoke();
worker.RunWorkerCompleted +=
(obj, arg) =>
{
MethodWhichMakesMyInterfaceReadWrite();
};
worker.RunWorkerAsync();
}
I wrote this before I realised you wanted async/await and tasks specifically - someone else has answered with that however. You can create whatever overloads you want for the extra params for your action.

Different methods using Functors/Delegates in c#

I have a method that I call multiple times, but each time a different method with a different signature is called from inside.
public void MethodOne()
{
//some stuff
*MethodCall();
//some stuff
}
So MethodOne is called multiple times, each time with a different *MethodCall(). What I'm trying to do is something like this :
public void MethodOne(Func<> MethodCall)
{
//some stuff
*MethodCall;
//some stuff
}
but the Methods that are called each have a different return type and different parameters. Is there a way to do this using Functors? If not, how would I go about doing this?
Thank you!
You best bet would be to use the non-generic Action type (or MethodInvoker would be the same), i.e.
public void MethodOne(Action callback)
{
//some stuff
if(callback != null) callback();
//some stuff
}
From this you can call any method by wrapping it at the caller, i.e.
MethodOne(SimpleMethod); // SimpleMethod has no parameters and returns void
MethodOne(() => MoreComplexMethod(1, "abc")); // this one returns void
MethodOne(() => { MethodThatReturnsSomething(12); }); // anything you like
etc
You cannot call a function which requires parameters without supplying them, so the answer is "no, not possible"
Also, maybe you want the following:
void MethodOne(Action a)
{
// some stuff
a();
// some stuff
}
... // somewhere in the code
MethodOne((Action)(() => { DoSomethingOther(1, 2, 3); }));
MethodOne((Action)(() => { DoSomethingEvenDifferent(1, 2, 3, 4, 5); }));
Every delegate in .Net is an instance of a class derived from Delegate. So if you really wish to pass 'any' delegate to a method, you can pass it as Delegate
To invoke it, you need to use its DynamicInvoke method.
public void MethodOne(Delegate MethodCall)
{
//some stuff
//Assuming you now have the required parameters
//or add params object[] args to the signature of this method
object res = MethodCall.DynamicInvoke(args); //args is object[] representing the parameters
//some stuff
}
But this is not recommended as DynamicInvoke is slow and it does not offer any compile time safety. Probably you should revisit your design.
This is basically not possible. You could make MethodOne generic for the return type, and use a lambda that closes over its outside block instead of parameters:
static void Main(string[] args)
{
int parameterSubst = 1;
int result = MethodOne<int>(() => parameterSubst);
string result2 = MethodOne<string>(() =>
{
string s = parameterSubst.ToString();
s += "foo";
return s;
});
}
static T MethodOne<T>(Func<T> function)
{
return function();
}
As you can see, parameterSubst is used in the passed Func<T>s, but not as a parameter.

C# ThreadPool wait on result

I want to have a function to something similar:
public static V callAsyncAndWait<V>(Func<V> func)
{
ThreadPool.QueueUserWorkItem(obj =>
{
V v = func.Invoke();
});
return v;
}
Obviously this code doesn't compile. What I want is to run the Func in another thread and return the result. How can I do that?
I recommend you to use the new .NET 4.0 Task class instead. Here is a tutorial on how to return a result from the execution of Task: http://msdn.microsoft.com/en-us/library/dd537613.aspx
Practically you have a very convenient property called Result, which, upon invocation of the getter, will block until the result is available.
That doesn't make too much sense. If the method is supposed to wait for the task to be finished, then you don't need a separate thread at all.
Something like "call async and notify when done" would make more sense:
void CallAsyncAndNotifyWhenDone<T>(Func<T> func, Action<T> callback)
{
ThreadPool.QueueUserWorkItem(obj =>
{
T result = func();
callback(result);
});
}
You can use async patternt to do it:
public static V callAsyncAndWait<V>(Func<V> func)
{
var asyncResult = func.BeginInvoke(null, null);
asyncresult.AsyncWaitHandle.WaitOne();
return func.EndInvoke(asyncResult);
}

ThreadPool in C#

I have two questions:
Is there a way to insert a ThreadPool functoin that dosen't gets
object as parameter(to insert a function to threadPool it need to be function that return void and ged one parameter -object) e.g i want to insert this function: double foo(int a,double b,string c)?
Is there a way to wait to thread in the pool (like join)?
For the first part, the easiest approach is probably:
Assuming a method per your description:
public double foo(int a, double b, string c)
{
...
}
You can queue this on the thread pool with:
ThreadPool.QueueUserWorkItem(o => foo(a, b, c));
For the second part, while you can't wait on a ThreadPool thread, you can call methods asynchronously on the thread pool, and wait on their completion (which seems to be what you're looking for).
Again, assuming the Foo method is defined as above.
Define a Delegate for Foo:
private delegate double FooDelegate(int a, double b, string c);
Then to call Foo asynchronously using the BeginInvoke/EndInvoke methods of the FooDelegate:
// Create a delegate to Foo
FooDelegate fooDelegate = Foo;
// Start executing Foo asynchronously with arguments a, b and c.
var asyncResult = fooDelegate.BeginInvoke(a, b, c, null, null);
// You can then wait on the completion of Foo using the AsyncWaitHandle property of asyncResult
if (!asyncResult.CompletedSynchronously)
{
// Wait until Foo completes
asyncResult.AsyncWaitHandle.WaitOne();
}
// Finally, the return value can be retrieved using:
var result = fooDelegate.EndInvoke(asyncResult);
To address the question raised in the comments. If you want to execute multiple function calls in parallel and wait for them all to return before continuing, you could use:
// Create a delegate to Foo
FooDelegate fooDelegate = Foo;
var asyncResults = new List<IAsyncResult>();
// Start multiple calls to Foo() in parallel. The loop can be adjusted as required (while, for, foreach).
while (...)
{
// Start executing Foo asynchronously with arguments a, b and c.
// Collect the async results in a list for later
asyncResults.Add(fooDelegate.BeginInvoke(a, b, c, null, null));
}
// List to collect the result of each invocation
var results = new List<double>();
// Wait for completion of all of the asynchronous invocations
foreach (var asyncResult in asyncResults)
{
if (!asyncResult.CompletedSynchronously)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
// Collect the result of the invocation (results will appear in the list in the same order that the invocation was begun above.
results.Add(fooDelegate.EndInvoke(asyncResult));
}
// At this point, all of the asynchronous invocations have returned, and the result of each invocation is stored in the results list.
The answer to both of these questions is no, not with the native ThreadPool, although you can achieve the same result if you package your input args into the state object and write mechanisms to provide wait functionality and get the result of the work item method.
http://smartthreadpool.codeplex.com/ does everything you want;
public static void Main(string[] args)
{
var threadPool = new SmartThreadPool();
IWorkItemResult<int> workItem=null;
SmartThreadPool.WaitAll(new IWaitableResult[ ]{workItem = threadPool.QueueWorkItem(new Amib.Threading.Func<int, int, int>(Add), 1, 2)});
Console.WriteLine(workItem.Result);
Console.ReadLine();
}
public static int Add(int a, int b)
{
return a+b;
}
Re your first question, create a new method of the correct signature (returns void, one object parameter) that calls foo. If you need to pass in specific arguments to foo then create a class or struct or use a Tuple<int, double, double> and cast it to object to pass it into ThreadMethod, then back to Tuple to get the arguments to foo.
void ThreadMethod(object obj)
{
var args = (Tuple<int, double, double>)obj;
foo(args.Item1, args.Item2, args.Item3);
}
Re. 2nd question, you'd have to create the thread yourself so you can keep a Thread object to join with.
For the first question
I think you can create a new class as a parameter
for exsample
interface IAction
{
void Do();
}
class SubClass : IAction
{
object _param;
public SubClass(object o)
{
_param = o;
}
public void Do()
{
// your current code in here
}
}
SubClass sc = new SubClass("paramter");
System.Threading.ThreadPool.QueueUserWorkItem(action => {
var dosomething = action as IAction;
dosomething.Do();
}, sc);
So , you donnt need to change any code in your current function ...
The classic way of doing it is below, however as Iridium has shown there's more compact ways of doing it now. If you're using .NET 4 you can use the parallel APIs or more precisely Tasks to make it even easier.
public class MyWorker
{
private int _a;
private double _b;
private string _c;
Action complete
public MyWorker(int a,double b,string c)
{
_a = a;
_b = b;
_c = c;
}
public void Run(object state)
{
double result = Foo();
}
private double Foo()
{
// Do something with _a, _b, _c
}
}
MyWorker worker = new MyWorker(1,1,"");
ThreadPool.QueueUserWorkItem(worker.Run);
There's an equivalent example on the MSDN page.
In terms of being notified when a thread in a threadpool is completed, you can use a WaitHandle
inside the object. Presumably you don't want to block until the thread is completed, in which
case an event, Action or Func in the MyWorker class would be another solution.
I'd recommend reading Joe Albahari's free ebook on Threading as covers the subjects in a lot more detail.

C# delegate for two methods with different parameters

I am using the following methods:
public void M1(Int32 a)
{
// acquire MyMutex
DoSomething(a);
// release MyMutex
}
and
public void M2(String s, String t)
{
// acquire MyMutex
DoSomethingElse(s, t);
// release MyMutex
}
From what I have found so far it seems that it is not possible to use a single delegate for two methods with different signatures.
Are there any other alternatives to write something like this:
public void UsingMutex(...)
{
// acquire MyMutex
...
// release MyMutex
}
UsingMutex(M1);
UsingMutex(M2);
All I can think for the moment is to use two delegates and a boolean flag to know which delegate to call, but it is not a long term solution.
It is possible to combine generics with delegates? And if so, do you have some links for any kind of documentation?
Environment: C# 2.0
Absolutely you can mix delegates with generics. In 2.0, Predicate<T> etc are good examples of this, but you must have the same number of args. In this scenario, perhaps an option is to use captures to include the args in the delegate?
i.e.
public delegate void Action();
static void Main()
{
DoStuff(delegate {Foo(5);});
DoStuff(delegate {Bar("abc","def");});
}
static void DoStuff(Action action)
{
action();
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Note that Action is defined for you in .NET 3.5, but you can re-declare it for 2.0 purposes ;-p
Note that the anonymous method (delegate {...}) can also be parameterised:
static void Main()
{
DoStuff(delegate (string s) {Foo(5);});
DoStuff(delegate (string s) {Bar(s,"def");});
}
static void DoStuff(Action<string> action)
{
action("abc");
}
static void Foo(int i)
{
Console.WriteLine(i);
}
static void Bar(string s, string t)
{
Console.WriteLine(s+t);
}
Finally, C# 3.0 makes this all a lot easier and prettier with "lambdas", but that is another topic ;-p
Yes, it's possible to combine generics with delegates.
public delegate void Action<T>(T x);
public delegate void Action<T,U>(T x, U y);
public void UsingMutex<T>(Action<T> x, T t) {
// acquire mutex...
x(t);
// release mutex...
}
public void UsingMutex<T,U>(Action<T,U> x, T t, U u) {
// acquire mutex...
x(t, u);
// release mutex...
}
But you still have to handle different number of parameters using overloads.
If you look at the Func<T> and Action<T> delegates in the framework, you'll see that they define a number of similar delegates with different number of parameters. You can use generics, but that doesn't solve the number of arguments issue you're talking about.

Categories

Resources