I'm trying to do this, but it doesn't work. Some suggestions?
int test_i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i);
test_i <- still is 0 and not 3!!!
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i)
{
DisableUi();
m_commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
ConnectToServer();
i = 3; <--------------------------
// This is the continuation that will be run
// on the UI thread
return () =>
{
EnableUi();
};
});
}
Why I can't set test_i to 3? I also tried ref and out, but it doesn't work.
What can I do to fix it?
EDIT
I've tried this, but ouside of this method dataSet still is empty.
public static void Select(DataGridView dataGridView, ref DataSet dataSet, params object[] parameters)
{
var _dataSet = dataSet;
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
_dataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
dataSet = _dataSet;
}
When passing the variable using the ref keyword, you can't use it inside a lambda expression. Try using a local variable inside the lambda and assign the ref variable outside it, if possible (somewhat simplified example):
private static void Main(string[] args)
{
int i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref i);
Console.WriteLine(i);
}
public static void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref int i)
{
int temp = i;
Thread t = new Thread(() =>
{
temp = 3; // assign the captured, local variable
});
t.Start();
t.Join();
i = temp; // assign the ref parameter
}
Update
In response to the updated answer: your problem is that _dataSet inside the lambda expression is not the same variable as dataSet outside the lambda expression. What you could do is the following:
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
Now we have a reference type with a property that we can safely modify inside the lambda expression:
public static void Select(DataGridView dataGridView,
DataSetContainer dataSetContainer,
params object[] parameters)
{
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
dataSetContainer.DataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
}
}
In the above code, the lambda expression will update the DataSet property of the DataSetContainer instance that is passed to the Select method. Since you are not modifying the passed argument itself but only a member of that instance there is no need for the ref keyword, and we also get around the closure issue.
Update 2
And now when I switched on my brain, I realize that the Select method makes an asynchronous call. It is quite likely as the code looks that the last line is the Select method will be executed long before _dataSet is being assigned, and as a result it will be null. To get around this you probably want to look into using some sort of signaling mechanism (such as ManualResetEvent or AutoResetEvent) to know when the assignment is done.
The i variable in the lambda expression refers to the parameter i of the method. As a workaround, you can make it to refer to a global variable (dirty solution).
By the way, you can't capture ref and out variables in lambdas, but you can have them as parameters. You need to change the signature of your delegate and the implementation of the method receiving the delegate, which might not be suitable:
(out int i) => { i = 10; }
Related
I have a class with a set of functions that differ in the number of parameters and the parameter types. I've been trying to figure out a way to invoke a call to a desired function inside an allocated thread.
What's a simple way of doing this? I've looked into System.Action, but that requires the parameters to be known. I've also gone over TaskFactory and TPL, but from the examples I've seen, I can't put together the solution in my head.
What I want to eventually do is queue up jobs that will be executed by a limited number of threads. The jobs performed are simple HTTP requests.
I feel like this has been done before and has a simple solution, but it has eluded me for weeks. I'm hoping for an elegant way of doing it instead of a lot of complex code.
I'm also trying to implement MEF plugins to make matters worse.
public bool AddThreads(int numOfThreads)
{
try
{
// Exit if no plugin type is set
if (PluginType == "") return false;
int totalThreads = numOfThreads + threads.Count;
for (int i = threads.Count; i < totalThreads; i++)
{
// Create an instance of the MEF plugin
var task = PluginHandler.CreateInstance(PluginType);
threads.Add(task);
task.ThreadId = i;
task.OnStatusChange += new TaskerPlugin.EventHandler(ChangeStatus);
task.OnActionComplete += new TaskerPlugin.EventHandler(ReportComplete);
task.OnActionSuccess += new TaskerPlugin.EventHandler(ReportSuccess);
task.OnActionFailure += new TaskerPlugin.EventHandler(ReportFailure);
task.OnActionAttempt += new TaskerPlugin.EventHandler(ReportAttempt);
task.OnActionError += new TaskerPlugin.EventHandler(ReportError);
task.OnActionCancelled += new TaskerPlugin.EventHandler(ReportCancellation);
task.OnActionBegin += new TaskerPlugin.EventHandler(ReportStartOfTask);
task.OnActionEnd += new TaskerPlugin.EventHandler(ReportEndOfTask);
// Do work from plugin
// This is where I'd like to call different
// functions possibly inside Start()
task.Start();
}
return true;
}
catch (Exception)
{
return false;
}
}
Current code calling the function:
private void CreateThreads(int threadCount)
{
// taskMan is a class variable to queue more jobs in the future
taskMan = new TaskManager(PLUGIN_FOLDER)
{
PluginType = PLUGIN_TYPE,
UseProxies = (_config.IpSolution == "Proxies" || _config.IpSolution == "Proxy URL")
};
taskMan.AddThreads(threadCount);
}
I want to eventually just call a function to add a job to it with a predefined number of threads:
private void AddJob(string pluginName, string methodName, List<string> args)
I'd prefer not just using a string list to put all of my arguments in, but I don't really know of another way of doing it. Maybe a list of objects which I then cast later? Both these ideas are very messy...
I am assuming that AddJob is the overloaded method that you need to call with different parameters.
You might have to tweak your PluginHandler.CreateInstance(PluginType) method to do something like this while creating the task, this would allow you to execute any method you need in the task that you create..
Task task = new Task(() =>
{
classInstance.YourMethod("some param1", some other param2));
}
Further with some reflection..
var classInstance = new YourClass();
Type type = classInstance.GetType();
MethodInfo methodInfo = type.GetMethod("AddJob");
object[] parametersArray = new object[] { "some param1", "some parma2" };
methodInfo.Invoke(methodInfo, parametersArray);
and finally,
Task task = new Task(() =>
{
var classInstance = new YourClass();
Type type = classInstance.GetType();
MethodInfo methodInfo = type.GetMethod("AddJob");
object[] parametersArray = new object[] { "some param1", "some parma2" };
methodInfo.Invoke(classInstance, parametersArray);
}
In case the AddJob method is present in the current class itself, there could be little changes to the code.
I have a Queue that holds a list of delegates that correspond to methods that I want to run in the future. I would like to only have singular instances of any particular method/parameter in queue. In other words, a queue of DoOne(), DoTwo(2), DoThree(3) should be possible where as a queue of DoOne(), DoTwo(2), DoTwo(2) should not be allowed.
I have noticed that _queue.Contains(Func< int >) works through the minimal testing that I have done, but I am worried if I am missing something. Is this a sufficient enough test to determine whether a particular method/parameter is queued, to satisfy what I am trying to accomplish?
Queue<Func<int>> _queue = new Queue<Func<int>>();
void Queue(Func<int> Method)
{
if (!_queue.Contains(Method))
_queue.Enqueue(Method);
}
void QueueOne()
{
Queue( () => DoOne() );
}
void QueueTwo(int val)
{
Queue( () => DoTwo(val) );
}
void DoOne()
{
return 1;
}
void DoTwo(int val)
{
return val;
}
Since each time you call QueueOne or QueueTwo, you create a new function that is passed to the Queue function, I have my doubts that you can find a way to compare those to each other and determine that they match.
This leads me to recommend that you pass an identifier that you will use to make the uniqueness comparison.
In my sample code below, I chose to do this using the CallerMemberName to identify the name of the calling function (i.e. "QueueOne" or "QueueTwo") and refuse to enqueue the item if the queue still had a matching entry.
Queue<Tuple<string, Func<int>>> _queue = new Queue<Tuple<string, Func<int>>>();
void Queue(Func<int> method, [CallerMemberName] string caller = null)
{
if (!_queue.Any(v => v.Item1 == caller))
_queue.Enqueue(Tuple.Create(caller, method));
}
void QueueOne()
{
Queue(() => DoOne());
}
void QueueTwo(int val)
{
Queue(() => DoTwo(val));
}
int DoOne()
{
return 1;
}
int DoTwo(int val)
{
return val;
}
Since you are calling with a parameter they are treated different objects (see Closures in c#)
Change your logicto check the duplication to:
if (!_queue.Where(x => x.Method == Method.Method).Any())
_queue.Enqueue(m);
this will help you to stop adding same method again (even if they have diff parameters)
I am in the process of refactoring "synchronous" code (i.e. uses Windows events to wait until some other thread finished doing something) to "asynchronous" code (using delegates to implement a callback mechanism).
In the sync code, I sometimes have local variables that I need to use after the wait is over. When code like that goes async, those local variables are lost (the callback handler can't access them). I can store them as class attributes, but it feels wasteful.
In C++, I use std::bind to work around this. I just add as many parameters as local variables needed to the callback handler, and bind them when I call the async method. For example, let's say that the async method callback receives an object of type CallbackParam and the caller uses two local variables of type LocalA and LocalB.
void AsyncClass::MethodWhichCallsAsyncMethod(){
LocalA localVarA;
LocalB localVarB;
// OnAsyncMethodDone will need localVarA and localVarB, so we bind them
AsyncMethod( std::bind( &AsyncClass::OnAsyncMethodDone, this, std::placeholders::_1, localVarA, localVarB ) );
}
void AsynClass::AsyncMethod( std::function<void(CallbackParam)> callback ){
CallbackParam result;
//Compute result...
if( callback )
callback( result );
}
void AsyncClass::OnAsyncMethodDone( CallbackParam p, LocalA a, LocalB b ){
//Do whatever needs to be done
}
Is there some sort of equivalent to this in C# and VB.NET? Using delegates or something else?
UPDATE: For completeness' sake, here is the C# equivalent of my example based on #lasseespeholt's answer:
using System;
public class AsyncClass {
public void MethodWhichCallsAsyncMethod() {
var a = new LocalA();
var b = new LocalB();
//Anonymous callback handler (equivalent to AsyncClass::OnAsyncMethodDone)
Action<CallbackParam> callback = result => {
//Do what needs to be done; result, a and b can be accessed
};
AsyncMethod( callback );
}
private void AsyncMethod( Action<CallbackParam> callback ) {
var result = new CallbackParam();
//Compute result...
if( callback != null )
callback( result );
}
}
UPDATE: This should almost certainly not be used. Use the async/await keywords in C#
You can exploit closures like the following:
void MethodWhichCallsAsyncMethod()
{
int foo = 1;
AsyncCallback callback = result =>
{
Console.WriteLine(foo); // Access to foo
};
AsyncMethod(callback);
}
void AsyncMethod(AsyncCallback callback)
{
IAsyncResult result = null; // Compute result
callback(result);
}
The compiler generates a class which contains "foo" so you don't save anything with this approach, but it's clean.
I have an issue with a Windows Forms application that I am creating. The application is supposed to be an integration testing application. Essentially, it's supposed to test the methods that utilize lots of web services in one of my classes. I am loading the methods from the class I want to test via reflection, and am doing so like this:
private List<string> GetMethods(Type type)
{
return (from method in type.GetMethods() where method.IsPublic &&
method.ReturnType == typeof(void) select method.Name).ToList();
}
This returns a list of the methods from that class that have been created to test the web services and places them in a ListBox where the user can select as many methods as he/she likes. My confusion comes in here. What I would like to do is get the methods selected by the user and execute the corresponding method X amount of times (there is a text box for entering the number of times to execute a method on the form as well). I can't figure out how to execute these methods based on the name of the method I got through reflection. I've tried something like this, but I know it's not right:
private void RunMethods(Type type)
{
var tester = new ClassToTest();
foreach(var item in lstMethodList.SelectedItems)
{
foreach(var method in type.GetMethods())
{
if(String.Equals(item.ToString(), method.Name))
{
ThreadStart ts = new ThreadStart(method.Name);
Thread thread1 = new Thread(ts);
thread1.Start();
}
}
}
}
This won't even compile, as a ThreadStart requires a method name as a parameter. Is there any way that this is possible to do? Maybe I'm going about it wrong logically, but I'd like to create a thread for each method that needs to be run and execute that method however many times the user specifies. This is supposed to be a way of doing integration testing along with some load testing to see what the web service can handle.
You can use something like this to get the methods you want:
private List<MethodInfo> GetMethods(Type type)
{
return (from method in type.GetMethods()
where method.IsPublic &&
method.ReturnType == typeof(void)
select method).ToList();
}
Then if you want to call the methods in separate threads you would write (will work only if the methods are static):
foreach(MethodInfo mi in GetMethods(SomeType) {
MethodInfo tempMi = mi;
Action myAction = (Action) Delegate.CreateDelegate(typeof(Action), tempMi);
ThreadStart ts = new ThreadStart(myAction);
Thread thread1 = new Thread(ts);
thread1.Start();
}
Or you would write (only if the methods have strictly no parameters, beware of inherited methods which may take parameters!):
foreach (MethodInfo mi in GetMethods(type))
{
MethodInfo tempMi = mi; //modified closure
object o = Activator.CreateInstance( type );
Action myAction = delegate() { tempMi.Invoke(o, null); };
ThreadStart ts = new ThreadStart(myAction);
Thread thread1 = new Thread(ts);
thread1.Start();
}
If the methods take parameters, you'd have to pass an array of object( object [] { ... } ) instead of null (in the Invoke method called on the current MethodInfo) accordingly; with of course corrects objects in the array.
It would actually be better if you take a List of Thread and add a new Thread in it for each MethodInfo in the list so you can keep control on them afterwards (like if you want to stop one). A HashMap would also be a good choice, the key being the MethodInfo or the Action and the value being the associated Thread.
You can create an instance of your class using Activator.
Then you can call one of its methods using Invoke.
Something like this should work:
private void RunMethods(Type type)
{
foreach( var item in lstMethodList.SelectedItems )
{
foreach( var method in type.GetMethods() )
{
if( String.Equals( item.ToString(), method.Name))
{
MethodInfo capturedMethod = method;
var t = new Thread( () => ThreadMain( type, capturedMethod ) );
t.Start();
}
}
}
}
static void ThreadMain( Type type, MethodInfo mi )
{
object o = Activator.CreateInstance( type );
object[] parameters = new object[] { };
mi.Invoke( o, parameters );
}
I've assumed the class being tested has a parameter-less constructor.
You can implement a private dictionary which holds the MethodInfos and Method name.
private Dictionary<string, MethodInfo> methodList;
private List<string> GetMethods(Type type)
{
methodList = new Dictionary<string, MethodInfo>();
type.GetMethods().Where(m=>m.IsPublic && m.ReturnType.Equals(typeof(void))).ToList().ForEach(m=>
methodList.Add(m.Name,m)
);
return methodList.Keys.Select(k => k).ToList();
}
on selecting the dropdown, you can find the method in the dictionary and execute it.
I can't explain an issue I've run across. Basically I get a different answer if I use lambda syntax in a foreach loop than if I use it in a for loop. In the code below I register a delegate in a "dispatcher" class. I then later wrap the delegate on the way out in another delegate and return a list of these wrapped delegates. I then execute them. The expected output of executing the wrapped function list is 1,2. However I don't see that when I combine a lambda and a foreach loop.
This is not the code that is causing the problem, but the simplest case I could make to reproduce it. I would prefer not to discuss use cases of this, I'm more curious as to why I get behavior I'm not expecting. If I use the foreach loop below with the lambda syntax it fails. If I use the new Action() syntax and a foreach it works, if I use the lambda syntax in a for loop it works. Can anyone explain what is going on here. This has me really stumped.
public class Holder
{
public Holder(int ID, Dispatcher disp)
{
this.ID = ID;
disp.Register(Something);
}
public int ID { get; set; }
private void Something(int test) { Console.WriteLine(ID.ToString()); }
}
public class Dispatcher
{
List<Action<int>> m_Holder = new List<Action<int>>();
public void Register(Action<int> func)
{
m_Holder.Add(func);
}
public List<Action<int>> ReturnWrappedList()
{
List<Action<int>> temp = new List<Action<int>>();
//for (int i = 0; i < m_Holder.Count; i++) //Works - gives 1, 2
//{
// var action = m_Holder[i];
// temp.Add(p => action(p));
//}
foreach (var action in m_Holder)
{
temp.Add(p => action(p)); //Fails - gives 2,2
//temp.Add(new Action<int>(action)); Works - gives 1,2
}
return temp;
}
}
class Program
{
static void Main(string[] args)
{
var disp = new Dispatcher();
var hold1 = new Holder(1, disp);
var hold2 = new Holder(2, disp);
disp.ReturnWrappedList().ForEach(p => p(1));
}
}
This is the infamous "closing over the loop variable" gotcha.
Closing over the loop variable considered harmful (and part two)
Have you tried:
foreach (var action in m_Holder)
{
var a = action;
temp.Add(p => a(p));
}
This is the classic issue of a captured closure with a scope that isn't what you expect. In the foreach, the action has outer scope, so the execution captures the last value of the loop. In the for case, you create the action in inner scope, so the closure is over the local value at each iteration.