I have a winform and some threads. When i try to access a field in the winform from one of the threads, the following error occurs :
Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.
How can i resolve this problem?
Regards,
Alexandru Badescu
All controls have a method called Invoke, which takes a delegate as the first argument and optional params object[].
You can use this method easily:
richTextBox1.Invoke(new MethodInvoker(DoSomething));
where
void DoSomething()
{
richTextBox1.BackColor = Color.Cyan;
}
The delegate MethodInvoker is in the System.Windows.Forms namespace, which, I suppose, you are already using.
You can even invoke from the same thread!
You can also use parameters, like this:
richTextBox1.Invoke(new ColorChanger(DoSomething), Color.Cyan);
where
delegate void ColorChanger(Color c);
void DoSomething(Color c)
{
richTextBox1.BackColor = c;
}
I hope this helped!
Edit:
InvokeRequired is required if you are using the same method from a... basically... unknown thread.
So it would look like this:
void DoSomething()
{
if (richTextBox1.InvokeRequired)
richTextBox1.Invoke(new MethodInvoker(DoSomething));
else
{
richTextBox1.BackColor = Color.Cyan;
// Here should go everything the method will do.
}
}
You may call this method from ANY thread!
And for parameters:
delegate void ColorChanger(Color c);
void DoSomething(Color c)
{
if (richTextBox1.InvokeRequired)
richTextBox1.Invoke(new ColorChanger(DoSomething), c);
else
{
richTextBox1.BackColor = c;
// Here should go everything the method will do.
}
}
Enjoy programming!
In your Thread code, before changing textBox1, check textBox1.InvokeRequired and if so, use textBox1.Invoke(aDelegate)
what Vercas suggested works fine, but if you love inline code you may also try to choose an anonymous delegate
richTextBox1.Invoke(new MethodInvoker(
delegate() {
richTextBox1.BackColor = Color.Cyan;
));
+1 to him :)
Salut Alexandru
You may want to check out an alternative way, the
BackgroundWorker
component. It is really easy and confortable to use. More details and samples you can find here
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
This component is also very important one in .NET and very usefull to know.
Related
I want to show a text in a label for a particular time so I did a search on google and I found these two solutions :
The first solution is :
public void InfoLabel(string value)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(InfoLabel), new object[] { value });
return;
}
barStaticItem3.Caption = value;
if (!String.IsNullOrEmpty(value))
{
System.Timers.Timer timer =
new System.Timers.Timer(3000) { Enabled = true };
timer.Elapsed += (sender, args) =>
{
this.InfoLabel(string.Empty);
timer.Dispose();
};
}
}
The second solution :
private void ShowTextForParticularTime(String caption)
{
Timer t = new Timer { Interval = 5000, Enabled = true};
t.Tick += (sender, args) => OnTimerEvent(sender, args, caption);
}
private void OnTimerEvent(object sender, EventArgs e, String caption)
{
barStaticItem3.Caption = caption;
}
Could you please tell me the deffrence between the two solutions, and why we use this symbole "=>" , also I understood nothing from this line :
if (InvokeRequired)
{
this.Invoke(new Action<string>(InfoLabel), new object[] { value });
return;
}
Okay, there is a good amount to explain here.
There is no major differences between the two options you have shown. The reason they look different is because the first id declaring a delegate method (lambda expression) inside the public method, while the second is just creating an event handler. They do almost the exact same thing. Infact you can see that in the delegate method you have the tradition event handler prameters (object sender, EventArgs e). Personally I prefer the second solution because it looks cleaner to me.
Invoke Required is used to handle threading. In C# errors will be thrown if a thread that didn't create a visual object tries to alter the visual object. To get around this we make a call to the thread that created the visual object by calling "Invoke". The "InvokeRequired" property just tells us if the current thread did not create the visual object. You should always use this when you are threading or making delegate methods (because you can't control the thread that runs them.)
I hope this brief explanation helps. Comment if it is unclear
In WinForms and WPF, the UI can only be updated from the thread that created the control in question. These two approach show two ways to update your UI from a different thread.
The first approach manually checks if the code is running on a different thread and, if it is, marshals the call to the UI thread.
The second approach uses an event, leaving the details of marshaling to .NET
The symbol => represents a lamda expression. You can think of it much like a function pointer (though sometimes it is really something called an expression tree behind the scenes). Essentially, it creates a variable that points to code that can be called by referencing that variable.
Either approach should work fine. Personally I prefer the second approach because it allows the framework to handle more of the plumbing work.
I am writing GUI applications for some time now and one thing I always use are MethodInvoker + lambda functions to do cross-thread access.
From the examples I find I always see stuff like this:
Version 1
if (InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
Label1.Text = "Foobar";
});
}
else
{
Label1.Text = "Foobar";
}
However this leads to code-duplication --> major baddie to me.
So what's wrong with this?
Version 2
MethodInvoker updateText = new MethodInvoker(() =>
{
Label1.Text = "Foobar";
});
if (InvokeRequired)
{
Invoke(updateText);
}
else
{
updateText();
}
Now I have the functionality bundled in one variable and call it with Invoke or as a function pointer when appropriate. Is version 2 worse performance-wise? Or is i bad practice to use anonymous functions for this?
Nothing's wrong with it... but you can add an extension method to make it all somewhat nicer:
public static void InvokeIfNecessary(this Control control,
MethodInvoker action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
Then you can write:
this.InvokeIfNecessary(() => Label1.Text = "Foobar");
Much neater :)
There is a very slight performance drawback from creating a delegate when you don't need to, but it's almost certainly insignificant - concentrate on writing clean code.
Note that even if you don't want to do that, you can still make your variable declaration simpler in your existing code:
MethodInvoker updateText = () => Label1.Text = "Foobar";
That's one benefit of using a separate variable - you don't need the new MethodInvoker bit to tell the lambda expression what type of delegate you want...
Is version 2 worse performance-wise? Or is i bad practice to use anonymous functions for this?
No version 2 is better, don't worry about performance problems with it. Instead of using an anonymous function you could also define a method:
public void SetLabelTextToFooBar()
{
Label1.Text = "Foobar";
}
and then:
if (InvokeRequired)
{
Invoke(SetLabelTextToFooBar);
}
else
{
SetLabelTextToFooBar();
}
or simply use a BackgroundWorker which will automatically execute all callbacks (such as RunWorkerCompleted and ProgressChanged) on the main UI thread so that you don't need to check for InvokeRequired.
Another practice on doing it:
Invoke((MethodInvoker)delegate
{
Label1.Text = "Foobar";
});
Right, this is my first venture into multi threading so could be something incredibly simple I'm missing but here goes...
I'm using thread pool to kick off a bunch of short running processes at the same time, each will be passed a URL to process/scrape for fb-tweets-google-plusones and return a result to my ReportProgress method by invoking the delegate ThreadDone but when passing in the processed object once the thread's done processing, i keep getting the error Method name expected but I'm passing in the method ReportProgress? I'm willing to bet (hoping) it's something incredibly simple that someone more experienced can spot right away. Here is what i have so far:
Delegate definition:
public delegate void ThreadDone(object sender, ScrapeResult scrapedResult);
DoWork:
public void DoWork(object sender)
{
while (true)
{
//lock the thread to prevent other threads from processing same job
lock (_threadLock)
{
string url = (string)sender;
result.URL = url;
if (chkFb.Checked)
{
result.Shares = grabber.GetFacebookShares(url);
}
if (chkTwitt.Checked)
{
result.Tweets = grabber.GetTweetCount(url);
}
if (chkPlusOne.Checked)
{
result.PlusOnes = grabber.GetPlusOnes(url);
}
this.Invoke(new ThreadDone(ReportProgress(sender, result))); //ERROR is on this line
}
Thread.Sleep(100);
}
}
ReportProgress:
private void ReportProgress(object sender, ScrapeResult scrapedResult)//<-- might not need?
{
progressBar.Value++;
ScrapeResult result = (ScrapeResult)sender;//ScrapedResult result = scrapedResult;
outputGrid.Rows.Add(result.URL, result.Shares, result.Tweets, result.PlusOnes);
outputGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
outputGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
}
Any help is greatly appreciated!
Change this:
this.Invoke(new ThreadDone(ReportProgress(sender, result)));
To:
this.Invoke(new ThreadDone(ReportProgress), sender, result);
The first parameter of Invoke() is the delegate, to build a delegate you do not need to give its parameters but only the method to call (that's why compiler says "method name expected") With new ThreadDone(ReportProgress) you create the new delegate and with 2nd and 3rd parameter of Invoke() you specify the parameters that will be passed to your delegate.
I would seriously consider using the TPL. Much cleaner to handle the finish of a task.
Hi i have some question related to call back feature in libraries created by user in c#
i have created a winform application named "Sample"
i have also created a class library named "Library"
Sample contains only one form that has a button say "CALL"
i have implemented all the coding part in a library
when i click on the call button on form then a method "ACTIVATE CALL" of the library is called.
this method performs some work on a thread.
What i want is when thread work if finished then "CALLBACK" method placed in my winform must be called.
To achieve this i have passed "this" reference of the form to the library
i collected "this" as obj "Object" type in formal arguement in library.
can anybody suggest me how to call callback method?
i tried this:
if(obj.GetType()== typeOf(what to specify here))
{
obj.callback();
}
hope somebody can provide me help.
note: both library and sample are different projects
how to achieve callback feature?
Define your library method with a callback.
public void ACTIVATE(object arg, object arg, Action callback)
{
// Do what you have to do here.
callback.Invoke();
}
Then, in your Sample WinForms client you can call something like this.
public void MethodInSample()
{
Library lib = new Library();
Action callback = () => { DoSomethingHere };
Lib.ACTIVATE(1,1,callback);
}
If you want the callback to return some parameters, you could use a Func<> instead and define the arguments that way.
Alternatively, you could use an event. The BackgroundWorker object is a good example of this. This class has a method called RunWorkerAsync(), which causes some work to be done on a background thread. There is then an event called RunWorkerCompleted which you listen on to indicate when the background thread has completed.
Both methods are valid I think, but the second has the benefit of allowing more than one party to listen for completion of the work.
Have the user of the ActivateCall function supply a callback so in you library:
function void ActivateCall(Action callback){
//Do Stuff
if (null != callback){
callback();
}
}
and then in your main form:
function button1_Click(object sender, EventArgs e){
library.ActivateCall(DoStuff);
}
There are a number of things to look out for though since you say you are doing stuff in a separate thread within the library call. If you are altering the GUI at all in the callback you will need to make sure you do the work in the GUI thread. You will also need to make sure you run the callback once all the work in the thread has been completed (I suspect).
To make sure your callback is run in the GUI thread (if required) do something like this:
function button1_Click(object sender, EventArgs e){
library.ActivateCall(DoStuff());
}
function void DoStuff(){
if (InvokeRequired(){
Invoke(DoStuff);
return;
}
//Do stuff here....
}
Finally i achieved this using Delegate+Event
*****************Sample class**************************
call()
{
//activate method of library is called
libraryObject.stop += new LibraryClass.callback(setCallbackMethod);
libraryObject.activate();
}
public void setCallbackMethod(String str)
{
// most important to be back on main thread
this.Invoke((MethodInvoker)delegate
{
btn.Enabled = true;
});
}
*******************Library***************************
public delegate void callback(String str);
public event callback stop;
activate()
{
//instantiates a thread/timer
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(CheckForMessage);
aTimer.Interval = 1000;
aTimer.Start();
}
public void CheckForMessage(object source, ElapsedEventArgs e)
{
//performs some work
//calls callback method of ui thread in sample code
if (stop != null)
{
stop("COMPLETED");
}
}
Which is more correct and why?
Control.BeginInvoke(new Action(DoSomething), null);
private void DoSomething()
{
MessageBox.Show("What a great post");
}
or
Control.BeginInvoke((MethodInvoker) delegate {
MessageBox.Show("What a great post");
});
I kinda feel like I am doing the same thing, so when is the right time to use MethodInvoker vs Action, or even writing a lambda expression?
EDIT: I know that there isn't really much of a difference between writing a lambda vs Action, but MethodInvoker seems to be made for a specific purpose. Is it doing anything different?
Both are equally correct, but the documentation for Control.Invoke states that:
The delegate can be an instance of
EventHandler, in which case the sender
parameter will contain this control,
and the event parameter will contain
EventArgs.Empty. The delegate can also
be an instance of MethodInvoker, or
any other delegate that takes a void
parameter list. A call to an
EventHandler or MethodInvoker delegate
will be faster than a call to another
type of delegate.
So MethodInvoker would be a more efficient choice.
For each solution bellow I run a 131072 (128*1024) iterations (in one separated thread).
The VS2010 performance assistant give this results:
read-only MethodInvoker: 5664.53 (+0%)
New MethodInvoker: 5828.31 (+2.89%)
function cast in MethodInvoker: 5857.07 (+3.40%)
read-only Action: 6467.33 (+14.17%)
New Action: 6829.07 (+20.56%)
Call to a new Action at each iteration
private void SetVisibleByNewAction()
{
if (InvokeRequired)
{
Invoke(new Action(SetVisibleByNewAction));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, Action at each iteration
// private readonly Action _actionSetVisibleByAction
// _actionSetVisibleByAction= SetVisibleByAction;
private void SetVisibleByAction()
{
if (InvokeRequired)
{
Invoke(_actionSetVisibleByAction);
}
else
{
Visible = true;
}
}
Call to a new MethodInvoker at each iteration.
private void SetVisibleByNewMethodInvoker()
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
}
else
{
Visible = true;
}
}
Call to a read-only, build in constructor, MethodInvoker at each iteration
// private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker
// _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
private void SetVisibleByMethodInvoker()
{
if (InvokeRequired)
{
Invoke(_methodInvokerSetVisibleByMethodInvoker);
}
else
{
Visible = true;
}
}
Call to the function cast in MethodInvoker at each iteration
private void SetVisibleByDelegate()
{
if (InvokeRequired)
{
Invoke((MethodInvoker) SetVisibleByDelegate);
}
else
{
Visible = true;
}
}
Example of call for the "New Action" solution :
private void ButtonNewActionOnClick(object sender, EventArgs e)
{
new Thread(TestNewAction).Start();
}
private void TestNewAction()
{
var watch = Stopwatch.StartNew();
for (var i = 0; i < COUNT; i++)
{
SetVisibleByNewAction();
}
watch.Stop();
Append("New Action: " + watch.ElapsedMilliseconds + "ms");
}
I prefer using lambdas and Actions/Funcs:
Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
Action is defined in System, while MethodInvoker is defined in System.Windows.Forms - you may be better off using Action, since it is portable to other places. You will also find more places that accept Action as a parameter than MethodInvoker.
However, the documentation does indicate that calls to delegates of type EventHandler or MethodInvoker in Control.Invoke() will be faster than any other type.
Aside from which namepsace they are in, I don't believe there is a meaningful functional difference between Action and MethodInvoker - they are essentially both defined as:
public delegate void NoParamMethod();
As an aside, Action has several overloads which allow parameters to be passed in - and it is generic so that they can be typesafe.
Also per MSDN:
MethodInvoker provides a simple delegate that is used to invoke a method with a void parameter list. This delegate can be used when making calls to a control's Invoke method, or when you need a simple delegate but do not want to define one yourself.
an Action on the other hand can take up to 4 parameters.
But I don't think there is any difference between MethodInvoker and Action as they both simply encapsulate a delegate that doesn't take a paremter and returns void
If you look at their definitions you'll simply see this.
public delegate void MethodInvoker();
public delegate void Action();
btw you could also write your second line as.
Control.BeginInvoke(new MethodInvoker(DoSomething), null);
It is a matter of preference in most cases, unless you intend to reuse the DoSomething() method. Also the anonymous functions will place your scoped variables on the heap, might make it a more expensive function.
Don't forget to somehow check if control is available at the moment, to avoid errors at closing form.
if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));