Invoke Best Practice - c#

Every time I update the view of my program from a thread other than the element was created from, I use:
if (this.table.InvokeRequired)
{
this.table.Invoke(new MethodInvoker(delegate
{
this.table.Controls.Add(newRow);
this.table.Controls.SetChildIndex(newRow, this.table.Controls.Count);
}));
}
else
{
this.table.Controls.Add(newRow);
this.table.Controls.SetChildIndex(newRow, this.table.Controls.Count);
}
Even though this approach works fine, I doubt that it's the best-practice to do it that way since
this.table.Controls.Add(newRow);
this.table.Controls.SetChildIndex(newRow, this.table.Controls.Count);
is basically the same for invoking and not invoking.
Any ideas how I could improve that?

You can put it in a method, then the method can invoke itself:
public void addRow(Control newRow) {
if (this.table.InvokeRequired) {
this.table.Invoke(new MethodInvoker(addRow), new object[]{ newRow });
} else {
this.table.Controls.Add(newRow);
this.table.Controls.SetChildIndex(newRow, this.table.Controls.Count);
}
}

The syntax might not be exactly right, but roughly:
delegate void myedelegate(<mystuff>)
void UpdateSomething(<mystuff>)
if(this.invokerequired)
{
mydelegate updater = new mydeleate(UpdateSomething);
updater.invoke(new object[]{<mystuff>})
}
else
{
//doupdate
}
Also, see http://www.codeproject.com/Articles/37642/Avoiding-InvokeRequired for a good guide on invoke required practices

Related

C# SetPropertyThreadSafe vs Invoke thread-safe calls

Which of these two methods are better to update the UI from another thread?
(for me they work both, but which is safer?)
I would prefer the SetPropertyThreadSafe method as it needs less code.
1.
label1.SetPropertyThreadSafe(() => this.label1.Text, "New Value");
2.
if (label1.InvokeRequired)
{
label1.Invoke(new MethodInvoker(delegate {
label1.Text="New Value"; }));
}
SetPropertyThreadSafe is not a method built in to .NET, if you are using this implmentation
public static TResult GetPropertyThreadSafe<TControl, TResult>(this TControl self, Func<TControl, TResult> getter)
where TControl: Control
{
if (self.InvokeRequired)
{
return (TResult)self.Invoke(getter, self);
}
else
{
return getter(self);
}
}
Then the two examples you posted are doing the exact same thing so there is no difference.
If you head
1.
label1.SetPropertyThreadSafe(() => this.label1.Text, "New Value");
label2.SetPropertyThreadSafe(() => this.label1.Text, "New Value2");
and 2.
if (label1.InvokeRequired)
{
label1.Invoke(new MethodInvoker(delegate
{
label1.Text="New Value";
label2.Text="New Value2";
}));
}
Then (2) is clearly better as it has a much lower overhead. But in your case there is nothing to choose between them.
If you know you are on another thread, there is no need for the "if InvokeRequired".

Function Invoke Thread

i´m a beginner in C#,
a start a new Thread
pollprintthread = new System.Threading.Thread(PollPrint);
pollprintthread.Start();
in this Thread i call a function with a Datagridview
void PollPrint()
{
(some code)
printausfueren();
(some code)
}
public void printausfueren()
{
(some Code)
object[] row = { sqlReader[0], sqlReader[1], sqlReader[3], sqlReader[2], sqlReader[4], sqlReader[5], sqlReader[6], sqlReader[7] };
dataGridViewPrint.Rows.Add(row);
(some Code)
}
but i can´t use printausfuheren().invoke, i found any tutorials but only for Static Methods
Please Help :)
You can find a good explanation here: https://stackoverflow.com/a/12179408/67038
However, I would recommend that you wrap your call to dataGridViewPrint.Rows.Add in a method and call that method instead.
You will want to do this because there may be other actions that you wish to take on the UI when you add those rows.
For example, if you are adding a lot of rows, you are going to want to call BeginEdit/EndEdit on the grid, so that it does not try to repaint itself for every row that you add:
public void printausfueren()
{
//(some Code)
object[] rows = { sqlReader[0], sqlReader[1], sqlReader[3], sqlReader[2], sqlReader[4], sqlReader[5], sqlReader[6], sqlReader[7] };
dataGridViewPrint.Invoke(new Action(() => LoadGrid(rows)));
//(some Code)
}
private void LoadGrid(object[] rows)
{
// only need BeginEdit/EndEdit if you are adding many rows at a time
dataGridViewPrint.BeginEdit(false);
dataGridViewPrint.Rows.Add(rows);
dataGridViewPrint.EndEdit();
}
You can easily use anonymous methods to do complex invokes, such as:
yourForm.Invoke( (MethodInvoker) delegate() { dataGridViewPrint.Rows.Add(row); } );
This will auto-magically capture the row instance etc.

Removing Text with an Invoke?

So, the documentation that I've found online so far regarding the Invoke property doesn't seem to be particularly good, which is actually kind of annoying, believe it or not. I understand what Invoke does - you can't safely access the GUI directly, so an invoke does it in a safe way. That's fine, but I don't understand the variables that go into the method. If I wanted to, for instance, remove text from a listbox, how would I do that? I get about this far before I get a bit lost.
private void DoStuff(string TextIWouldBeRemoving)
{
if (listboxname.InvokeRequired)
{
listboxname.Invoke(SomeMysteriousParamaters, new object[] { TextIWouldBeRemoving )};
}
}
The first parameter is the method you want to safely invoke, the second parameter is an object array of the arguments to that method
So you would write:
private void DoStuff(string TextIWouldBeRemoving)
{
if (listboxname.InvokeRequired)
{
listboxname.Invoke(DoStuff, new object[] { TextIWouldBeRemoving )};
}
else
{
// Actually remove the text here!
}
}
Invoke is all about threading.
You need to do an invoke whenever you have created a separate thread in your code, and you need to update the User Interface elements from withing the code, that is executing in that newly create thread.
You can use a BeginInvoke, instead of a synchronous Invoke method. This article has a good example:
http://msdn.microsoft.com/en-us/library/0b1bf3y3.aspx
private void button1_Click(object sender, EventArgs e)
{
if (listBox1.InvokeRequired)
{
Action<string> d = DoAnything;
listBox1.Invoke(d, new object[] { "Item 1" });
}
else
DoAnything("Item 1");
}
void DoAnything(string itemText)
{
listBox1.Items.Remove(itemText);
}

Stop a loop inside a method in C#

Is there any way to stop a running loop inside another method or insert a break statement dynamically in C#?
Thanks
Edit : I want to be able to dynamically intercept the method and insert a break to stop the loop when an event gets triggered in another function.I have several instances of the class and I want to stop the loop in each instance whenever required and manage all the instances. Consider multiple instances to be in a generic list
Example :
List<myclass> objlist=new List<myclass>();
foreach(myclass obj in objlist)
{
obj.loopingfunction().BreakLoop //or something like this (assuming that the loopingfunction is already called)
}
I need this because I want to break the loop once the user stores some huge amount of data.When the user imports the data,I get a event fired. But I cannot keep checking the database from multiple instances since it screws up sqlserver.
This is in an ASP.Net application.
If the whole thing is running in a single thread, it wouldn't make any sense. If the loop is running, then nothing else is running at the same time. If you're running a loop on another thread and the controlling method on another thread, you can either abort the loop thread completely or check a flag inside the loop to decide whether or not you should break and set the flag appropriately in the controlling method.
Update: make that function return a boolean value indicating whether you should break and use it in an "if" statement:
if (myFunctionShouldBreakLoop()) break;
Another option would be to raise a CancelEventArgs during every iteration of the loop. Probably not the most efficient, but another option nonetheless:
private void SomeMethod()
{
for (int i = 0; i <= 100000; i++)
{
Console.WriteLine(i);
if (LoopIncrement != null)
{
CancelEventArgs args = new CancelEventArgs();
LoopIncrement(null, args);
if (args.Cancel)
{
break;
}
}
}
And then elsewhere:
myObj.LoopIncrement += MyHandler;
private void MyHandler(object sender, CancelEventArgs e)
{
if(someCondition)
{
e.Cancel = true;
}
}
This way you can somewhat control the loop from outside....
Have the condition in a locked property.
private Boolean BreakCondition
{
get { lock(_LockObject) { return _BreakCondition; } }
set { lock(_LockObject) { _BreakCondition = value; } }
}
private Boolean _BreakCondition = false;
private Object _LockObject = new Object();
if (this.BreakCondition)
{
break;
}
How about using iterators, and yield magic to solve the problem.
Here is an article on infinite lists that might be useful
http://www.codethinked.com/post/2009/02/04/Infinite-Lists-With-C-Yield.aspx
class Program
{
static void Main(string[] args)
{
Predicate<int> when = i => i > 100 && Console.ReadKey().KeyChar.ToString() == "0";
foreach(var i in Numbers().BreakOn(when))
{
Console.WriteLine(i);
}
Console.ReadLine();
}
private static IEnumerable<int> Numbers()
{
var i = 0;
while(true)
{
yield return i++;
}
}
}
public static class Util
{
public static IEnumerable<int> BreakOn(this IEnumerable<int> sequence, Predicate<int> when)
{
foreach(int i in sequence)
{
if(when(i))
{
yield break;
}
yield return i;
}
}
}
I think you can use flag
bool stop = false;
for(int i=0;i<num;i++)
{
if(stop) break;
}
The short answer is: no. If you don't control the code, then you can't cause the loop to terminate.
If you do control the code, you could build in some sort of cooperation, but it sounds messy. Maybe you can elaborate on why?

Accessing Class members with Invoke from a different thread in C#

Note: Part of a series: C#: Accessing form members from another class and How to access form objects from another cs file in C#.
Hello,
The Idea is to notify the user using the memo when a packet is received/sent in a TCP Client.
After couple of fixes,the most suitable solution seemed to be this one
public string TextValue
{
set
{
this.Memo.Text += value + "\n";
}
}
That's how it's being called
var form = Form.ActiveForm as Form1;
if(form != null)
form.TextValue = "Test asdasd";
However,calling the code throws an exception ,because of Unsafe thread call.I found a solution at msdn,but I can't seem to acquire the method they've used there.
This is my remake,which doesn't work.
private void SetTextMemo(string txt)
{
if(this.Memo.InvokeRequired)
{
this.Invoke(SetTextMemo,txt); //error here
}
else
{
this.Memo.Text += txt + "\n";
}
}
errors:
Argument '1': cannot convert from 'method group' to 'System.Delegate'
Argument '2': cannot convert from 'string' to 'object[]'
Basically,I'm trying to access the Memo(or more likely said,add text to the memo) from another thread using Invoke.I never used it before,maybe that's why I misunderstand my mistake.
The easy way is:
this.Invoke((MethodInvoker)delegate {
this.Memo.Text += txt + "\n";
});
Which uses an anonymous method to do the job inline. Since you expect to be on another thread, you may as well just call Invoke - it is safe even from the UI thread.
If you're using C# 3.0 and the 3.5 framework try the following
if ( this.Memo.InvokeRequired ) {
this.Invoke((Action)(() => SetTextMemo(txt)));
}
Your implementation assumes that the method will not infinitely recurse because the behavior of the InvokeRequired property will prevent it. This assumption may proove to be true, but there's no problem coding the function to avoid this possibility entirely. Here's what I suggest:
private void SetMemo(string txt)
{
Memo.Text = txt;
}
private delegate void MemoSetter(string txt);
public void ThreadSafeSet(string txt)
{
Invoke(new MemoSetter(SetMemo), txt);
}
I used to handle all this cross-thread business, but recently I went with AOP, where you simply decorate a method to execute on the UI thread. Here's an example (from PostSharp):
public class FormsThreadAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
Form f = (Form)eventArgs.Delegate.Target;
if (f.InvokeRequired)
f.Invoke(eventArgs.Delegate, eventArgs.GetArgumentArray());
else
eventArgs.Proceed();
}
}

Categories

Resources