I'm using the Task class in C# and want to pass a predefined method that returns a value and not using lambdas to the Task.Run method.
Here is a console app with the code:
static int ThreadMethod()
{
return 42;
}
static void Main(string[] args)
{
Task<int> t = Task.Run(function:ThreadMethod);
WriteLine(t.Result);
}
However, it is returning this error:
The call is ambiguous between the following methods or properties: 'Task.Run<TResult>(Func<TResult>)' and 'Task.Run(Func<Task>)'
I tried doing this to fix it and got my expected result:
Task<int> t = Task.Run((Func<int>)ThreadMethod);
However, I am not sure if I'm doing it right or are there any better solution?
Fix your .Run argument like in this example. Can be copied and pasted into LinqPad to test.
public static void Main(string[] args)
{
Task<int> t = Task.Run(() => ThreadMethod());
WriteLine(t.Result);
}
public static int ThreadMethod()
{
return 42;
}
If you want to see it as a variable to pass check out below:
public static void Main(string[] args)
{
//Func<int> is saying I want a function with no parameters
//but returns an int. '() =>' this represents a function with
//no parameters. It then points to your defined method ThreadMethod
//Which fits the notions of no parameters and returning an int.
Func<int> threadMethod = () => ThreadMethod();
Task<int> t = Task.Run(threadMethod);
Console.WriteLine(t.Result);
}
public static int ThreadMethod()
{
return 42;
}
Here is the Documentation on Func(T), on the left hand menu you can select the different variations of Func() objects.
Related
I want to create a method that receives a method as a parameter and delay var. And execute the method after delay:
public static void performSelectorAfterDelay<T>(Action<T> method, T parameter, double delay)
{
Thread thread = new Thread(delegate()
{
Thread.Sleep(TimeSpan.FromSeconds(delay));
uc.BeginInvoke((Action)(() => method(parameter)));
});
thread.Start();
}
I want it to be Generic so i will be able to call it for these two methods:
public void funcA()
{
}
public void funcB(int num)
{
}
When i call it:
performSelectorAfterDelay(new Action(funcA), null, kSecondsWaitAfterTransferToFollowersPage);
performSelectorAfterDelay(new Action(funcB), 5, kSecondsWaitAfterTransferToFollowersPage);
I get this error:
The type arguments for method performSelectorAfterDelay(System.Action, T, double)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Any idea what can be the problem?
The compiler can't work out the type, because you're passing null as the 2nd parameter.
performSelectorAfterDelay(new Action(funcA), null, kSecondsWaitAfterTransferToFollowersPage);
Anyway, after you resolve that issue you will end up with another error, because funcB takes an int, so it cannot be passed into new Action because Action requires a parameterless method.
You may be able to get it working using Action<object> as per the other answer, but that will mean you can't leave funcA without a parameter. However, this solution seems redundant to me unless I'm misunderstanding something. You can just pass an actual Action that calls funcA/funcB with their parameters like so:
public void performSelectorAfterDelay(Action method, double delay)
{
Thread thread = new Thread(delegate ()
{
Thread.Sleep(TimeSpan.FromSeconds(delay));
method();
});
thread.Start();
}
public void test()
{
performSelectorAfterDelay(() => funcA(), kSecondsWaitAfterTransferToFollowersPage);
performSelectorAfterDelay(() => funcB(1), kSecondsWaitAfterTransferToFollowersPage);
}
The error message tells something.
Here is the fixed version sir:
public static void funcA(object obj)
{
}
public static void funcB(int num)
{
}
public static void performSelectorAfterDelay<T>(Action<T> method, T parameter, double delay)
{
Thread thread = new Thread(delegate()
{
Thread.Sleep(TimeSpan.FromSeconds(delay));
uc.BeginInvoke((Action)(() => method(parameter)));
});
thread.Start();
}
public static void SomeCall()
{
performSelectorAfterDelay(new Action<object>(funcA), null, kSecondsWaitAfterTransferToFollowersPage);
performSelectorAfterDelay(new Action<int>(funcB), 5, kSecondsWaitAfterTransferToFollowersPage);
}
I found this code (no conpiler error, it's mean code no error) that is "PingCompletedEventHandler" has constructor like PingCompletedEventHandler(abc) with static void abc(object s, PingCompletedEventArgs e){} right?
static PingCompletedEventHandler Ping_completed(object s, PingCompletedEventArgs e)
{
// This code work fine, it used method void abc below
PingCompletedEventHandler a = new PingCompletedEventHandler(abc);
value.Add("abc");
lock (#lock)
{
instances -= 1;
}
if (e.Reply.Status == IPStatus.Success)
{
string abcd = string.Concat("Active IP: ", e.Reply.Address.ToString());
value.Add("abc");
value.Add(abcd);
result += 1;
}
return a;
}
static void abc(object s, PingCompletedEventArgs e)
{
}
How can they do this. I have tested in my code, it doesn't work. Here is my test:
class Class1
{
static void abcd(int a){
}
public
// Error here: Class1.abcd(int)' is a 'method' but is used like a 'type'
Class1(abcd)
{
}
}
class Class3
{
public static void Main()
{
Class1 asd = new Class1();
}
}
When creating event-handlers you provide a pointer to method within the handlers constructor. This is not "a void", it is a delegate pointing to a method of type void.
The constructor therefor should look similar to:
delegate void HandlerMethod(objects s, PingCompletedEventArgs e);
class PingCompletedEventHandler {
PingCompletedEventHandler(HandlerMethod handler) { ... }
}
Now you can call this constructor with new PingCompletedEventHandler(abc) as abc is a method of type void expecting a param of type objectand of of type PingCompletedEventArgs.
Further reading on delegates here on MSDN
EDIT: Since .NET 3.0 there is also the easier to read Action-type that can be used for methods that do not return anything (void). Thus you may also use PingCompletedEventHandler(Action<object, PingCompletedEventArgs> handler) instead of defining your own delegate.
Further EDIT: To get this to work for your test, your constructor for Class1 should look like this: Class1(Action<int> theAction).
When you want a Function as a Parameter of a Method or a Constructor then you have to use a Delegate
The easiest way is using a Action<...> if you have a Void return type or a Func<T, ...> if you have something else as return type.
In your case it will look like this:
public ClassConstructor(Action<YourParameter> myDelegate)
{
}
For Example:
This is a very simple function and you want to create a delegate of this:
private static int Add(int a, int b)
{
return a + b;
}
then you need a delegate that accepts an int as return type and two ints as parameters.
So you define a Func<...> like this and assign the original method:
Func<int, int, int> addDelegate = Add;
the usage is like using Add only with an other name:
var result = addDelegate(2, 5);
I get an error here saying that the program could not exit the infinite loop.
public static class Program
{
public static void Main(string[] args)
{
Object obj = new Object();
Console.WriteLine(obj.GetClassName());
}
public static string GetClassName(this object value)
{
return value.GetClassName();
}
}
you need to change your extension method to say:
return obj.GetType().Name;
your extension method is calling itself which is causing the infinite loop/recursion problem.
I'm trying to do a simple example but I'm not even getting the basics. What's wrong with this code? Imagine Calculate() takes a few seconds.
static void Main(string[] args)
{
int result = await Calculate();
Console.WriteLine(result);
Console.ReadLine();
}
static async Task<int> Calculate()
{
return 1;
}
Simply change your main to:
static void Main(string[] args)
{
int result = Calculate().Result;
Console.WriteLine(result);
Console.ReadLine();
}
As soon as you use the await keyword, the surrounding method must be marked as async which - as others metnioned - is not possible for Main.
Since async methods like Calculate still return good old Task objects, feel free to use the "old" way of dealing with them: using Result to wait for results. Of course this is a blocking operation - but no reason to be non-blocking inside Main, right? ;)
You can do this:
static void Main()
{
WrapMain();
}
static async void WrapMain()
{
int result = await Calculate();
Console.WriteLine(result);
Console.ReadLine();
}
static async Task<int> Calculate()
{
return await Task.Run(() =>
{
return 1;
});
}
I am trying to figure out how to return an action from a method. I cannot find any examples of this online. Here is the code I am trying to run but it fails:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
var testAction = test("it works");
testAction.Invoke(); //error here
Console.ReadLine();
}
static Action<string> test(string txt)
{
return (x) => Console.WriteLine(txt);
}
}
}
The problem is textAction is an Action<string>, which means you need to pass a string:
textAction("foo");
I suspect you want something like:
class Program
{
static void Main(string[] args)
{
var testAction = test();
testAction("it works");
// or textAction.Invoke("it works");
Console.ReadLine();
}
// Don't pass a string here - the Action<string> handles that for you..
static Action<string> test()
{
return (x) => Console.WriteLine(x);
}
}
The action that you are returning accepts a string as it's parameter. When you Invoke it you need to supply that parameter:
testAction("hello world");
Of course, your action ignores that parameter, so the more appropriate fix is to change the action so that it accepts no parameters:
static Action test(string txt)
{
return () => Console.WriteLine(txt);
}
Now your program will work as expected.
Since what you have is an Action<String> your invoke needs to include the string your actioning on.
testAction.Invoke("A string");
should work
The action you want to create should be parameterless, so that you can call it without parameters. So change the return type of test, and also drop that x that you declared but never used:
static Action test(string txt)
{
return () => Console.WriteLine(txt);
}
Then the calling code will work:
var testAction = test("it works"); // store the string in txt
testAction.Invoke();
Console.ReadLine();