Trying to start a thread based on a users choice - c#

I have a Combobox with many choices. What the user chooses takes them to a case statement. In this case one of the items that gets choosen is a string. Now this string I want to use to take start a specific function thread. e.g. I have function
public void DoWorkAP(){}
and another
public void DoWorkAG(){}
From the Combo box the user makes a choice and the case statemtn will have a string called sWhichWork and that is set to either "DoWorkAG" or "DoWorkAP"
Now in the UI code I have a thread
Thread t = null;
And when a button is pressed a function is called and in this function I have
t = new Thread(sWhichWork);
t.Start();
This seemed good as I woudl exect sWhichWork to be substituted with "DoWorkAG" or "DoWorkAP" but instead I get
"cannot convert from 'string' to System.Threading.ParameterizedThreadStart' "
Now I take out the SWhichWorks and have the following
t = new Thread(DoWorkAG);
t.Start();
This is good as it compiles and takes me to the correct place. So the question is how can I have a variable string choosen from the combox to the case stament take me to the same place?

If you have only two options, I'd go for
t = new Thread(sWhichWork == "DoWorkAG" ? DoWorkAG : DoWorkAP);
This would work as well:
t = new Thread(this.getType().GetMethod(sWhichWork).Invoke(this, new object[]));

You just switch on the thread:
var action = myComboBox.Text;
new Thread(() => {
if (action == "1") F1();
else F2();
});
Super simple.

Related

Better understanding of how control.InvokeRequired works

First, I have Windows app with a couple of methods.
One within main Form class:
private void generate_button_Click(object sender, EventArgs e)
{
GenerationThreads nw = new GenerationThreads();
nw.control = testlabel;
// nw.DelegateUpdater();
Thread tr1 = new Thread(new ThreadStart(nw.DelegateUpdater));
tr1.Start();
Thread.Sleep(100);
and two in GenerationThreads class:
public void DelegateUpdater()
{
string envelope = "*Envelope was brought safely.*";
string iterations = "";
for (int x = 1; x <= 3; x++)
{
iterations = iterations + x.ToString() + " iterations done.\n";
PassToLegate(iterations);
Thread.Sleep(400);
}
PassToLegate(iterations + envelope);
}
private void PassToLegate(string text)
{
if (control.InvokeRequired == true)
{
var hat = new Legate(PassToLegate);
string message = text + " (Legate involved)";
control.Invoke(hat, new object[] {message});
}
if (control.InvokeRequired == false)
{
control.Text = text + " (Legate not involved)";
}
}
When DelegateUpdater() is called directly after pressing button, like in commented part - without making a new thread - it just nicely executes three for() spins, displaying them all at once, with an annotation, that Legate wasn't involved at the end - as it's supposed to.
But when a new thread is involved, apart from having said for() display neatly sequenced, I also get both annotations - that the Legate was and wasn't involved.
Why is control.InvokeRequired() acting like true and false at the same time? Why does
if(control.InvokeRequired == false)
{
control.Text = text + " (Legate not involved)";
}
the "text" variable in this particular fragment seem empty? When it's being milled by delegate as "message" - it isn't. And finally, why, after deleting this part of the code completely, the control doesn't show any of the new data at all - even though it was supposed to pass through delegate already? Clearly something about the mechanics still eludes me and I can't put the finger on it. If someone could please explain, what is the real data flow in here.
Thanks!
I also get both annotations - that the Legate was and wasn't involved.
You get both annotations because the code to each is executed.
You first get the " (Legate involved)" annotation because when the PassToLegate() method is first called, the code is executing in the wrong thread. I.e. InvokeRequired returns true. Thus the annotation is appended to the original text value passed to the method.
In that same block of code, you then call control.Invoke(hat, new object[] {message});. And the delegate variable hat has been initialized to new Legate(PassToLegate);. That causes the PassToLegate() method to be called again, but on the UI thread instead. The new message value, i.e. the text value with the " (Legate involved)" annotation appended, is passed as the parameter.
So the method is called a second time, this time on the UI thread. And in that case, the InvokeRequired is now false, and you add the annotation " (Legate not involved)". Since the text parameter passed already had the " (Legate involved)" annotation appended to it, now both annotations are part of the string value assigned to the Text property.
For what it's worth, it is my opinion that the code should never bother with InvokeRequired. It is safe to call Invoke() when you are on the UI thread already (though of course ideally one would never do that), and so the Invoke() method itself has to do the equivalent of checking InvokeRequired anyway. You might as well just always call Invoke() all the time and keep the code simpler.
Even better would be to use higher-level abstractions such as BackgroundWorker, Progress<T>, and async/await (the last one being especially preferable when appropriate). Then you don't need to deal with the Invoke() method at all; the cross-thread invocations are handled automatically for you.

How to programically change the function name I call

I am trying to call a function based on information from a combobox. The user will change the combobox and in doing so we call a function according to the data in the combobox text joined with a fixed text. I am trying to do this so every time we get a new version I just add a folder and do not have to go into the code to add new function names like in a case statement.
The combobox would have text as
v6.1
v6.4
v7.2
v8.6
and so on
The function I want to call is named Getinfo_ with the addition of the text from the combobox with the . replaced with _ e.g. I would choose v6.1 from combobox and in doing so I would call function called Getinfo_v6_1
After a lot of thinking searching and trying I have got close but not close enough yet. I think I need to use Reflection (maybe not) and
private void cmbobx_version_SelectedIndexChanged(object sender, EventArgs e)
{
Type t = this.GetType(); //need to get the type
MethodInfo method = t.GetMethod("Getinfo" + cmbobx_version.Text.Replace('.', '_')); //put together function name
method.Invoke(this, new object[] {Fridge, "Order" }); //call function with parameters
}
Unfortunately this stops at invoke saying the method is NULL, I do not understand why this is so apart from maybe I totally misunderstand what I am doing.
The function I want to call would look a bit like the following
public void Getinfo_v6_1(ComboBox inFocusComboBox, string action)
{
switch (inFocusComboBox.Text)
{
case "Red": Price = 11254; break;
case "Blue": Price = 11278; break;
case "Green": Price = 11354; break;
}
}
public void Getinfo_v6_4(ComboBox inFocusComboBox, string action)
{
switch (inFocusComboBox.Text)
{
case "Red": Price = 254; break;
case "Blue": Price = 278; break;
case "Green": Price = 354; break;
}
}
All help greatly appreciated even if you have a better way of doing what I need to do.
You should read about design patterns for example you could create polymorphic items that implement your function using for example the template design pattern. Try to avoid reflection as it is ‘slow’ and not type safe.
Thanks to Ĵošħ Williard I had indeed missed out the underscore and when working with it I had not noticed as I also do a text replace from . to _ and thought it was all correct. Even when debugging I did not see it, often we cannot see the obvious which is why a second opinion of those wiser than me is always good.
The working code is now as follows.
private void cmbobx_version_SelectedIndexChanged(object sender, EventArgs e)
{
Type t = this.GetType(); //need to get the type
MethodInfo method = t.GetMethod("Getinfo_" + cmbobx_version.Text.Replace('.', '_')); //put together function name
method.Invoke(this, new object[] {Fridge, "Order" }); //call function with parameters
}
Please do be careful as the functions will have no references but it will compile and will work. It all works at run-time when you call the correct function.

Function that accepts mutliple, but specified enums

How can I restrict a function argument to a some specific enums? Preferably check it at compile-time (though I doubt this is possible).
What I have are 2 enums (KeyCode for keyboard keys and Mouse.Button for mouse buttons) and they are treated in the code in exactly the same way. I could simply overload the function and copy-paste the contents, but well, I'd like to avoid the nightmares.
Simplified version of what I currently have (inside a class)
enum E1 { Zero, One, Two }
enum E2 { Three, Four, Five }
// Overloads so users can only use this with enums only of type E1 or E2
public void DoEnumStuff(E1 e) {
DoEnumStuffTemplate(e);
}
public void DoEnumStuff(E2 e) {
DoEnumStuffTemplate(e);
}
// private function so users cannot access this generic one
private void DoEnumStuffTemplate<T>(T e) where T : struct, IConvertible {
// check type for safety
if (!typeof(T).IsEnum || typeof(T).Name != "E1" || typeof(T).Name != "E2")
throw new ArgumentException();
// do lots of stuff
DoSomething(e); //<- overloaded function, accepts only E1 and E2 =ERROR
// do lots of other stuff
}
For completeness sake:
DoSomething behaves completely different depending on which type is given
DoSomething is called a lot in the function
I cannot change the Enums
I do not want to change DoSomething
I think I need to be able to tell the compiler that the generic T is surely either E1 or E2, but I have no clue as of how to do this.
Edit: the situation
Lots of good suggestions, but nothing that encompasses all I want. I'll add here the code I currently have to shed some more light on the problem hopefully.
I'm making a minesweeper clone to try out Unity 2D. I've created an Action class based on the thor::ActionMap class from the library Thor in C++ used with SFML. It simply allows for neat code such as (in C++)
ActionMap actionMap<string>;
actionMap["Fire"] = Action(Keyboard::LeftControl) || Action(Mouse::Left);
// stuff
while (game.IsRunning()) {
if (actionMap["Fire"].IsActive()) //true if left control or left mouse button is held
// FIRE
// probably more stuff
}
Where ActionMap is simply a dictionary of a key (here a string) and an Action. As you can see, the Action accepts both keyboard and mouse buttons which are 2 different enums. Thus the equivalent of the DoSomething(e) from the example code.
I'm now creating a method that can change the controls consistently. It uses the enum EControls as key instead of a string. Here KeyCode contains all keyboard keys and Mouse.Button all the mouse buttons. I need to differentiate between pressing and releasing of a button here, which is why both EControls.TilePressed and EControls.TileReleased will have the same key and need to be treated differently than for example EControls.GameEscape. This code is again in C#.
private ActionMap _controls = new ActionMap<EControls>();
// Set controls for a keyboard key
public void SetControl(EControls control, KeyCode key) {
switch (control) {
// If either TilePressed or Released was given, set them both to the same key
case EControls.TilePressed:
case EControls.TileReleased:
//Here Action(...) is DoSomething(...) from the example code
_controls[EControls.TilePressed] = new Action(key, Action.EActionType.PressOnce);
_controls[EControls.TileReleased] = new Action(key, Action.EActionType.ReleaseOnce);
break;
case EControls.TileFlagPressed:
case EControls.TileFlagReleased:
_controls[EControls.TileFlagPressed] = new Action(key, Action.EActionType.PressOnce);
_controls[EControls.TileFlagReleased] = new Action(key, Action.EActionType.ReleaseOnce);
break;
case EControls.GameEscape:
_controls[EControls.GameEscape] = new Action(key, Action.EActionType.ReleaseOnce);
break;
default:
throw new ArgumentOutOfRangeException("control");
}
}
// Set controls for a mouse button
public void SetControl(EControls control, Mouse.Button button) {
// copy-pasted code :(
case EControls.TilePressed:
case EControls.TileReleased:
_controls[EControls.TilePressed] = new Action(button, Action.EActionType.PressOnce);
_controls[EControls.TileReleased] = new Action(button, Action.EActionType.ReleaseOnce);
break;
case EControls.TileFlagPressed:
case EControls.TileFlagReleased:
_controls[EControls.TileFlagPressed] = new Action(button, Action.EActionType.PressOnce);
_controls[EControls.TileFlagReleased] = new Action(button, Action.EActionType.ReleaseOnce);
break;
case EControls.GameEscape:
_controls[EControls.GameEscape] = new Action(button, Action.EActionType.ReleaseOnce);
break;
default:
throw new ArgumentOutOfRangeException("control");
}
}
As you can see, in almost every line of code new Action(...) is present and code such as if (typeof(T).GetType() == typeof(E1)) is essentially the same as copy-pasting the contents of the function. Which is something I'd like to avoid (copy-pasting would even be safer on compile-time). But as it stands, it does not seem to be possible.
Since in a bigger game you'll probably regularly add some new controls, it will be quite an annoyance.
Sorry for the wall of text :s
Here's a refactoring that resembles the Factory pattern:
public void SetControl(EControls control, Func<Action.EActionType, Action> createAction)
{
switch (control)
{
case EControls.TilePressed:
case EControls.TileReleased:
_controls[EControls.TilePressed] = createAction(Action.EActionType.PressOnce);
_controls[EControls.TileReleased] = createAction(Action.EActionType.ReleaseOnce);
break;
case EControls.TileFlagPressed:
case EControls.TileFlagReleased:
_controls[EControls.TileFlagPressed] = createAction(Action.EActionType.PressOnce);
_controls[EControls.TileFlagReleased] = createAction(Action.EActionType.ReleaseOnce);
break;
case EControls.GameEscape:
_controls[EControls.GameEscape] = createAction(Action.EActionType.ReleaseOnce);
break;
default:
throw new ArgumentOutOfRangeException("control");
}
}
// Call it later with:
SetControl(control, type => new Action(key, type));
SetControl(control, type => new Action(mouseButton, type));
You provide SetControl with what amounts to a partially filled constructor, createAction, that only needs the EActionType to fully create the Action.
Another way to do this (while changing more code) would be to invert the dependency: give the Action a way to set its own EActionType based on a passed in EControls.
I think overloading is your best bet. Factor do lots of stuff and do lots of other stuff into methods of their own, and you won't have any nightmares.
If that's really impossible, then what you have is fine. Just cast e to either E1 or E2 as appropriate. It's a little gross, but it's a private method so the ugliness shouldn't spread too far.
An ugly, but a way:
private void DoEnumStuffTemplate<T>(T e) where T : struct, IConvertible
{
if (typeof(T) == typeof(E1))
DoEnumStuff((E1)(object)e);
else if (typeof(T) == typeof(E2))
DoEnumStuff((E2)(object)e);
else
throw new ArgumentException();
}
Make sure nobody see it.
You don't want to change DoSomething, but would wrapping it be ok?
private void myDoSomething(T e) where T : struct, IConvertible
{
if (typeof(T).GetType().Name == "E1")
DoSomething((E1)(object)e);
else if (typeof(T).GetType().Name == "E2")
DoSomething((E2)(object)e);
else
throw new ArgumentException();
}
// private function so users cannot access this generic one
private void DoEnumStuffTemplate<T>(T e) where T : struct, IConvertible {
// check type for safety
if (!typeof(T).IsEnum || typeof(T).GetType().Name != "E1" || typeof(T).GetType().Name != "E2")
throw new ArgumentException();
// do lots of stuff
myDoSomething(e); //<- overloaded function, accepts only E1 and E2 =ERROR
// do lots of other stuff
}
You need to create the Action in two steps. The caller of SetControl(...) knows whether the source is a mouse button or a key. So the caller creates the action object like new Action(key) or new Action(button).
This action object is passed to the SetControl(control, Action action) method.
SetControl knows the action type. It needs a method in Action where the action type can be set, e.g. Action.SetActionType(Action.EActionType actionType).
So the SetControl method is:
// Set controls for an action
public void SetControl(EControls control, Action action) {
switch (control) {
// If either TilePressed or Released was given, set them both to the same key
case EControls.TilePressed:
case EControls.TileReleased:
//Here Action(...) is DoSomething(...) from the example code
_controls[EControls.TilePressed] = action.SetActionType(Action.EActionType.PressOnce);
_controls[EControls.TileReleased] = action.SetActionType(Action.EActionType.ReleaseOnce);
break;
case EControls.TileFlagPressed:
case EControls.TileFlagReleased:
_controls[EControls.TileFlagPressed] = action.SetActionType(Action.EActionType.PressOnce);
_controls[EControls.TileFlagReleased] = action.SetActionType(Action.EActionType.ReleaseOnce);
break;
case EControls.GameEscape:
_controls[EControls.GameEscape] = action.SetActionType(Action.EActionType.ReleaseOnce);
break;
default:
throw new ArgumentOutOfRangeException("control");
}
}
This method is called like so:
SetControl(control, new Action(key));
SetControl(control, new Action(mouseButton));

Visual Studio during Debugging: The function evaluation requires all threads to run

I'm suddenly getting a strange error while debugging. Up to now the variable in the watch windows has been showing correctly. Now I am always getting this error message in the watch windows:
The function evaluation requires all threads to run
I am not able to check any variable anymore. I am not explicitly working with threads. What can I do to get it working again?
I already disabled, as mentioned in some forums, the function: "Enable property Evaluation and other implicit function Calls" in the option window of the debugger. But without success, and it gives me this error:
Error Implicit Function evaluation disabled by the user
From the msdn forum:
This isn't an error in and of itself, but more of a feature of your debugger.
Some properties require code to be executed in order for the property to be read, but if this requires cross-thread interaction, then other threads may have to run as well. The debugger doesn't do this automatically, but certainly can, with your permission.
Just click the little evaluate icon and it will run your code and evaluate the property.
For further details on this behaviour check this excelent article
I ran into this issue when just trying to get items from a table called "AGENCY" using Entity Framework:
var agencies = db.AGENCY.OrderBy(e => e.FULLNAME);
Hovering over agencies in debug mode, clicking to expand the options, and clicking Results would give the dreaded "The function evaluation requires all threads to run" with a "Do Not Enter" icon at the end that, on which, clicking did nothing.
2 possible solutions:
Add .ToList() at the end:
var agencies = db.AGENCY_TABLE.OrderBy(e => e.FULLNAME).ToList();
List<AGENCY_TABLE> agencies = db.AGENCY_TABLE.OrderBy(e => e.FULLNAME).ToList();
Credit goes to Hp93 for helping me come to this solution. In the comments on MUG4N's answer where I found this solution, it also mentions trying .Any() instead of .ToList(), but this gives a Boolean instead of a <T>, like <AGENCY> is, so it probably wouldn't help.
Workaround - try a different path in the debug options. I found that I could click on the "Non-Public Members" > "_internalQuery" > ObjectQuery > Results View and get my values that way.
MUG4N has indeed provided a correct answer however if you hover over the line of code in debug, you may be looking at something like the below. If so, click the little re-evaluate icon highlighted in the image below...
NB: I obtained this image by pinning, normally the re-evaluate icone are in the middle of the window and not down the left hand column.
You should make thread safe call because accessing Windows form controls are not Thread safe in multithreading.
This is my simple code which makes Thread safe call and sets Progress bar.
public partial class Form1 : Form
{// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void StringArgReturningVoidDelegate(string text);
private Thread demoThread = null;
public int Progresscount = 0;
static EventWaitHandle waithandler = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
}
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
{
using (var stream = client.OpenRead("http://www.google.com"))
{
return true;
}
}
}
catch
{
return false;
}
}
public void Progressincrement()
{
waithandler.WaitOne();
while (CheckForInternetConnection()==true)
{
if (Progresscount==100)
{
break;
}
SetLabel("Connected");
Progresscount += 1;
SetProgress(Progresscount.ToString());
Thread.Sleep(TimeSpan.FromSeconds(1));
}
if (Progresscount <100)
{
Startthread();
}
SetLabel("Completed");
}
public void Startthread ()
{
this.demoThread= new Thread(new ThreadStart(Progressincrement));
this.demoThread.Start();
SetLabel("Waiting for connection");
while (CheckForInternetConnection() == false) ;
waithandler.Set();
}
private void SetLabel(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.label1.InvokeRequired)
{
StringArgReturningVoidDelegate d = new StringArgReturningVoidDelegate(SetLabel);
this.Invoke(d, new object[] { text });
}
else
{
this.label1.Text = text;
}
}
private void SetProgress(string Value)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.progressBar1.InvokeRequired)
{
StringArgReturningVoidDelegate d = new StringArgReturningVoidDelegate(SetProgress);
this.Invoke(d, new object[] {Value});
}
else
{
this.progressBar1.Value = Convert.ToInt32(Value);
}
}
private void Form1_Load(object sender, EventArgs e)
{
Startthread();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Responsive");
}
}
For more information MSDN
This isn't an error, but more of a feature of your debugger.
The debugger doesn't do this automatically, but certainly can, with users permission. Just click the little space icon and it will run the code and evaluate the property.
I use the next workaround to pass:
var OtherThreadField = "";
Invoke(new MethodInvoker(delegate
{
OtherThreadField = ExecuteNeededMEthod();
}));
Now i have a value for OtherThreadField.
I faced the same issue and solved .The Issue arise due to username and password ,in SQL connection there is user and password but in code there no user and password. so I enable the user and the password and the issue solved
For me, this happened when trying to break on a line that accesses a complex object instance contained by a Settings Class.
A breakpoint on the following if results in Settings.Default.FindSettings with the value being "The function evaluation requires all threads to run." If I press the force eval button, it is null. Stepping with the force eval button click or not enters the if block and initializes the object. If I remove the breakpoint and add a new breakpoint following the if block, the Settings.Default.FindSettings deserializes properly with the expected values.
if (Settings.Default.FindSettings == null)
{
Settings.Default.FindSettings = new FindSettings();
}
After trial and error, I added the following code before the above if block to access the settings prior to breaking. This seems to reliably fix the problem. I do not need it in production so I wrap in conditional compiler directive. I have a comment in the code instead of a non-descript discard:
#if DEBUG
var _ = Settings.Default.FindSettings;
#endif
I am not sure if the above line would be optimized out in production since it has side effects. As I only need it while debugging, I have not checked.

Best way to measure (and control) the refresh time of some itens of the user interface

My app needs to display the process time of some operations. One of the process times is the time spent to refresh the proces times at the UI ( got it? :D ).
The frequency of the operations can vary from 0 to about 100 Hz (10 ms).
The process times are display in some labels. To set it values I use this static method:
public Class UserInteface
{
//Static action to SafeSetControlText
private static Action<Control, string> actionSetControlText = delegate(Control c, string txt) { c.Text = txt; };
//Control
//Set Text
public static void SafeSetControlText(Control control, string text, bool useInvoke = false)
{
//Should I use actionSetControlText or it is ok to create the delegate every time?
Action<Control, string> action = delegate(Control c, string txt) { c.Text = txt; };
if (control.InvokeRequired)
{
if (useInvoke)
control.Invoke(action, new object[] { control, text });
else
control.BeginInvoke(action, new object[] { control, text });
}
else
action(control, text);
}
}
Questions:
I dont want to freeze all my UI tryng to update the process times, so how should I control when is it ok to refresh? Now Im doing something like: only update if last update time was 100 ms before now.
If I use BegingInvoke, is it possible to overflow the queues with too much calls?
How can I measure the UI refresh time using BeginInvoke? The best way is to use Invoke?
Pretty acceptable solution, by me, cause if you do not control it, it can result on data blinking on UI side.
No, I don't think you can overflow, especially on 10 ms, speed.
If you want to be sure on time measuring (as much as it possible) the solution is definitely is using of Invokde. The same ou an use also in production.
But this is something you gonna to measure against your specific application requirements.

Categories

Resources