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);
}
Related
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'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.
// This method never gets called
public void DoSomethingWithByte(byte b)
{
Writeline(b);
}
class Test<T>
{
public Test(Action<T> act, T data)
{
Dispatcher.Current.BeginInvoke(act, data);
}
}
void TestAll()
{
new Test<Byte>(DoSomethingWithByte, 6);
}
this does not work, why?
It compiles, gets to the line, but does not call the method
Why is this happening?
Act doesn't have a method to call, it is null.
Action<byte> act = ((byte b) DoSomethingwithByte(b));
Then have your method.
public void DoSomethingWithByte(byte b) {}
Take the following classes as an example.
public class A
{
// ...
void Foo(S myStruct){...}
}
public class B
{
public A test;
// ...
void Bar()
{
S myStruct = new S();
test.Foo(myStruct);
}
}
Now, I want the method-call test.Foo(myStruct) to be an asynchronous call ('fire-and-forget'). The bar-method needs to return as soon as possible. Documentation around delegates, BeginInvoke, EndInvoke, the ThreadPool etc. isn't helping me find a solution.
Is this a valid solution?
// Is using the `EndInvoke` method as the callback delegate valid?
foo.BeginInvoke(myStruct, foo.EndInvoke, null);
You are not required to call EndInvoke; not calling it merely means:
You don't get the return value from the method.
Any exceptions thrown during the method execution will simply disappear.
It sounds like you want to 'fire-and-forget', so the easiest way to do this is to use an anonymous delegate, for example:
var del = new Action(foo.Bar);
del.BeginInvoke(iar =>
{
try
{
del.EndInvoke(iar);
}
catch (Exception ex)
{
// Log the message?
}
}, null);
This is what happens when you execute this code:
A new thread is allocated (put simply) for the delegate.
The thread is given the delegate del and the anonymous delegate (iar => ...).
The thread executes del.
When it is finished executing (or an exception occurs) the result or exception is stored and the anonymous delegate is executed.
Inside the anonymous delegate, when EndInvoke is called the result from the method is either returned, or the exception is thrown (if one occurred).
Note that the above example is very different from:
// This is pointless and is still, essentially, synchronous.
del.EndInvoke(del.BeginInvoke(null, null));
Edit: You should always call End*. I've never found a scenario where not calling it presents a problem, however that is an implementation detail and is relying on undocumented behavior.
Finally your solution would crash the process if an exception is thrown, you can simply pass null as the delegate if you don't care about the exception (del.BeginInvoke(myStruct, null, null);). So as a final example what you are looking for is probably:
public class A
{
// ...
void Foo(S myStruct){...}
void FooAsync(S myStruct)
{
var del = new Action<S>(Foo);
del.BeginInvoke(myStruct, SuppressException, del);
}
static void SuppressException(IAsyncResult ar)
{
try
{
((Action<S>)ar.AsyncState).EndInvoke(ar);
}
catch
{
// TODO: Log
}
}
}
I would say that your best option is to use the ThreadPool:
void bar()
{
ThreadPool.QueueUserWorkItem(o=>
{
S myStruct = new S();
test.foo(myStruct);
});
}
This will queue the snippet for execution in a separate thread. Now you also have to be careful about something else: if you have multiple threads accessing the same instance of A and that instance modifies a variable, then you must ensure that you do proper synchronization of the variable.
public class A
{
private double sum;
private volatile bool running;
private readonly object sync;
public A()
{
sum = 0.0;
running = true;
sync = new object();
}
public void foo(S myStruct)
{
// You need to synchronize the whole block because you can get a race
// condition (i.e. running can be set to false after you've checked
// the flag and then you would be adding the sum when you're not
// supposed to be).
lock(sync)
{
if(running)
{
sum+=myStruct.Value;
}
}
}
public void stop()
{
// you don't need to synchronize here since the flag is volatile
running = false;
}
}
You can use the Callback model explained # What is AsyncCallback?
That way your EndInvoke will not be in bar(), but in a separate callback method.
In the example, the EndRead (corresponding to EndInvoke is in the callback method called CompleteRead rather than the calling method TestCallbackAPM corresponding to bar)
This is an option:
ThreadPool.QueueUserWorkItem(bcl =>
{
var bcList = (List<BarcodeColumn>)bcl;
IAsyncResult iftAR = this.dataGridView1.BeginInvoke((MethodInvoker)delegate
{
int x = this.dataGridView1.Rows[0].Cells.Count - 1;
for (int i = 0; i < this.dataGridView1.Rows.Count - 1; i++)
{
try
{
string imgPath = bcList[i].GifPath;
Image bmpImage = Image.FromFile(imgPath);
this.dataGridView1.Rows[i].Cells[x].Value =bmpImage;
}
catch (Exception)
{
continue;
}
}
});
while (!iftAR.IsCompleted) { /* wait this*/ }
}, barcodeList);
I have inherited some verbose, repetitious code that I am trying to refactor. The bare bones of which are as follows:
private void startThreads()
{
RunRemoteCmdDelegate runRemoteCmdDlg = new RunRemoteCmdDelegate(services.runRemoteCommand);
List<IAsyncResult> returnTags = new List<IAsyncResult>();
// asynchronously invokes the delegate multiple times
foreach (...)
{
returnTags.Add(runRemoteCmdDlg.BeginInvoke(...));
}
MonitorTasks(runRemoteCmdDlg, messages, returnTags, invokationCounter);
}
private void MonitorTasks(RunRemoteCmdDelegate theDelegate, List<IAsyncResult> returnTags)
{
foreach (IAsyncResult returnTag in returnTags) {
MessageType message = runRemoteCmdDlg.EndInvoke(returnTag);
messages.Add(message)
}
}
There are many classes containing this same code but all with different delegate types.
I'd like to 'pull up' the MonitorTasks method into a base class, but it will need to work with all the different types of delegate, for example:
private void MonitorTasks(Delegate theDelegate, List<IAsyncResult> returnTags)
{
foreach (IAsyncResult returnTag in returnTags) {
MessageType message = runRemoteCmdDlg.EndInvoke(returnTag); // DOESN'T COMPILE
messages.Add(message)
}
}
I can't call EndInvoke() on the base Delegate (or MulticastDelegate) type, so how can I code this method? Do I need to approach this in a different way?
I'm using C#3.5, so is there some way to use Func, Action, etc, and still be able to call EndInvoke?
You can use reflection to access the EndInvoke() method of the delegate:
using System.Reflection;
private void MonitorTasks(Delegate theDelegate, List<IAsyncResult> returnTags)
{
MethodInfo endInvoke = theDelegate.GetType().GetMethod("EndInvoke",
new Type[] { typeof(IAsyncResult) });
foreach (IAsyncResult returnTag in returnTags) {
MessageType message = (MessageType) endInvoke.Invoke(theDelegate,
new object[] { returnTag });
messages.Add(message);
}
}
See this blog for a more general, fire-and-forget take on the problem.