I have gotten a bit lazy(it's sometimes good) and started updating WinForms UI by invoking a callback without checking InvokeRequired first.
Are there a performance issues or considerations that I should be aware of?
private delegate void SetStatusEventHandler(string statusMessage);
private void SetStatus(string statusMessage)
{
Invoke((MethodInvoker) (() =>
{
resultLabel.Text = statusMessage;
}));
// - vs -
if (InvokeRequired)
{
SetStatusEventHandler cb = SetStatus;
Invoke(cb, statusMessage);
}
else
{
resultLabel.Text = statusMessage;
}
}
[EDIT]: Most of times that a method that calls "invoke" will be called at most like say 10~20 times a second with a wide interval inbetween.
[UPDATE] Settled with the following extension method
public static class SmartInvoker
{
public static void InvokeHandler(this Control control, MethodInvoker del)
{
if (control.InvokeRequired)
{
control.Invoke(del);
return;
}
del();
}
}
...
private void SetStatus(string statusMessage)
{
this.InvokeHandler(() => resultLabel.Text = statusMessage);
}
I guess finding out how to manage extension method classes is another topic I need to dig in. Thank you for your help
EDIT: See the comments for debate about the whole posting vs immediately dispatching malarky.
Either way, my answer is actually the same: unless this is happening hugely often unnecessarily (i.e. most of the time you're on the UI thread to start with, and it's attached to something like a mouse movement handler) I wouldn't worry. It certainly makes the code simpler. If this is going to be invoked very often, I'd measure and test more :)
Invoke is faster with an EventHandler or MethodInvoker delegate than with others. I don't know if there's any difference between the two - you may want to check.
You can make this even simpler by writing an extension method, e.g.
public static void InvokeHandler(this Control control, MethodInvoker handler)
{
control.Invoke(handler);
}
Then you can make your code:
private void SetStatus(string statusMessage)
{
this.InvokeHandler(delegate
{
resultLabel.Text = statusMessage;
});
}
or
private void SetStatus(string statusMessage)
{
InvokeHandler(() => resultLabel.Text = statusMessage);
}
That way you don't need to specify the delegate type.
Why not just add an extension method so you don't have to think about it anymore?
public static object SmartInvoke(this Control control, MethodInvoker del) {
if ( control.InvokeRequired ) {
control.Invoke(del);
return;
}
del();
}
Now your code becomes
private void SetStatus(string statusMessage) {
this.SmartInvoke(() => resultLabel.Text = statusMessage);
}
I believe it just prevents an unnecessary post if you're already on the same thread. So if that would be the most common scenario (being on the correct thread), it might cause a small performance hit by not checking, but I dont believe its actually required.
Related
I am working on a VS project/solution that is used by different applications. My job is to refactor the project and change it from using xxxAsync method to using BeginInvoke.
I came up to something similar to the following code:
public class AsyncTestModel {
private delegate string DoTaskDelegate();
public static EventHandler<TaskCompletedEventArgs> OnTaskCompleted;
public static void InvokeTask() {
DoTaskDelegate taskDelegate = Task;
taskDelegate.BeginInvoke(new AsyncCallback(TaskCallback), null);
}
private static string Task() {
Thread.Sleep(5000);
return "Thread Task successfully completed.";
}
private static void TaskCallback(IAsyncResult ar) {
string result = ((DoTaskDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
if (OnTaskCompleted != null) {
OnTaskCompleted(null, new TaskCompletedEventArgs(result));
}
}
}
public class TaskCompletedEventArgs : EventArgs {
private string _message;
public TaskCompletedEventArgs(string message) : base() {
_message = message;
}
public string Message {
get {
return _message;
}
}
}
I've tested this on a new UI project I've created. The UI project contains a button and a label controls. The UI has the following code:
private void button1_Click(object sender, EventArgs e) {
AsyncTestModel.OnTaskCompleted += OnTaskCompleted;
AsyncTestModel.InvokeTask();
}
private void OnTaskCompleted(object sender, TaskCompletedEventArgs e) {
UpdateLabel(e.Message);
}
private void UpdateLabel(string message) {
this.label1.Text = message;
}
After running this, I've encountered the cross-thread exception saying the the control 'label1' is being accessed from other thread aside the thread that it was created.
Is there a way for me to invoke the OnTaskCompleted event handler on the same thread that calls the BeginInvoke method? I know I could just use the form's InvokeRequired and call the form's BeginInvoke like the following:
private delegate void DoUpdateLabelDelegate(string message);
private void UpdateLabel(string message) {
if (this.InvokeRequired) {
IAsyncResult ar = this.BeginInvoke(new DoUpdateLabelDelegate(UpdateLabel), message);
this.EndInvoke(ar);
return;
}
this.label1.Text = message;
}
But the solution above will require me to ask and apply that solution to the other development team handling applications that uses my project/solution. Those other developers shouldn't be required to know that the methods hooked to the event handler are running from different thread.
Thanks, in advance.
As designed, no, you have absolutely no idea which thread is the one on which the client's UI runs.
You can arbitrarily demand that your InvokeTask() is to be called from that UI thread. Now you know, you can copy SynchronizationContext.Current in the InvokeTask() method and, later, call its Post() or Send() method to call a method that fires the event. This is the pattern used by, for example, BackgroundWorker and async/await. Do note that copying the Current property is required to make this work, don't skip it.
That of course still won't work when your InvokeTask() method is not called from the UI thread, you'll see that Synchronization.Current is null and have no hope to marshal the call. If that's a concern then you could expose a property of type ISynchronizeInvoke, call it SynchronizingObject. Now it is up to the client code to make the call, they'll have no trouble setting the property, they'll simply assign this in their form class constructor. And you use the property's Post or Send method to call the method that raises the event. This is the pattern used by for example the Process and FileSystemWatcher classes. Don't use it if you expect your library to be used by non-Winforms client apps, unfortunately later GUI libraries like WPF and Silverlight don't implement the interface. Otherwise the exact same problem with approaches like calling Control.Begin/Invoke() yourself.
try to use this, maybe it can help you.
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//Do something...
});
I can't quite come up with the solution to creating a generic method to handle the InvokeRequired for void methods (I'll deal with return values later). I was thinking something like:
// Probably not the best name, any ideas? :)
public static void CheckInvoke(this Control instance,
,Action<object, object> action)
{
if (instance.InvokeRequired)
{
instance.Invoke(new MethodInvoker(() => action));
}
else
{
action()
}
}
Then I could write something like:
public partial class MyForm : Form
{
private ThreadedClass c = new ThreadedClass();
public MyForm()
{
c.ThreadedEvent += this.CheckInvoke(this
,this.MethodRequiresInvoke
,sender
,e);
}
}
This doesn't compile obviously, I just can't quite tie it together.
Hans is correct, in that you probably don't want to wrap code like this up, especially since it can cause some debugging issues down the road in determining what thread actions are happening on. That said, this would be the signature you'd want:
public static class FormsExt
{
public static void UnwiseInvoke(this Control instance, Action toDo)
{
if(instance.InvokeRequired)
{
instance.Invoke(toDo);
}
else
{
toDo();
}
}
}
Loose Action parameters of "object,object" (as JerKimball suggests), name it SafeInvoke, and attach to event via anonymous delegate:
c.ThreadedEvent += delegate
{
c.SafeInvoke(this.MethodRequiresInvoke);
};
I have numerous functions that are called from a background thread, but then need to perform a GUI operation. Therefore in each function, I switch context to the GUI thread. However I'm wondering if my code can be improved?
Here's a cut down example of how my code typically looks now:
public void FunctionABC(string test)
{
// Make sure we are in the GUI thread.
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => FunctionABC(test))); return;
}
// main body of function
}
The main part I have a problem with is having to mention my own function name explicitly in the context switch (I partly dislike this because I keep forgetting to change the name when I copy and paste the code!)
Any ideas for a more generic way of switching context, e.g. is any way of calling back into my own function via some clever pointer that avoids naming the function explicitly?
Something like this snippet would be good (which doesn't build however):
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => this(test))); return;
Thoughts?
How about pulling the dispatch code into a separate method?
public void Dispatch(Action action)
{
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
else
{
action();
}
}
and:
Dispatch(() => FunctionABC(test));
You can take this reusable method:
private void ExecuteOnDispatcherThread(Action action)
{
if (!this.Dispatcher.CheckAccess()) {
this.Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
else {
action();
}
}
And invoke it like this:
this.ExecuteOnDispatcherThread(() => FunctionABC(test));
Is it possible to design a method in such a fashion, that it knows it must automatically call a next method in succession upon exiting?
In the following example, I must call Refresh() to cause my form to repaint after this event takes place. The problem is that, it's ugly to call Refresh() after, for example, 20 different events which must make the form refresh. e.g
private void PriorityLine_Click(object sender, EventArgs e)
{
_showPriorityLine = (_showPriorityLine) ? false : true;
Refresh(); // Must call refresh for changes to take effect.
}
I suppose what I'm looking for is some kind of signature I can apply to the method to cause it to automatically chain to the next method, regardless from where its called. e.g
(I know this isn't syntactically correct.)
private void PriorityLine_Click(object sender, EventArgs e).Refresh()
{
_showPriorityLine = (_showPriorityLine) ? false : true;
}
I want to seperate the interface of the method, from the logic contained within the method. I understand it would be the exact amount of effort, if not more. For example, if I were to edit the method and accidently removed Refresh, it would cause my application to break. Whereas, if the Refresh method was outside of the actual logic of the method, I could do anything within the method without worrying about removing the next chain of logic.
Sounds like what you want is Aspect Oriented Programming, there are a number of different frameworks to enable you to have stuff "magically" happen after some set of methods have run, have a look here AOP programming in .Net?
I'm not aware of any really clean way. One method would be to use PostSharp.
You could encapsulate the changes which would cause the form to refresh into form-level properties.
For instance,
private bool _showPriorityLine;
private bool ShowPriorityLine
{
get { return _showPriorityLine; }
set
{
_showPriorityLine = value;
Refresh();
}
}
Then your event would just be
private void PriorityLine_Click(object sender, EventArgs e)
{
ShowPriorityLine = !ShowPriorityLine;
}
Of course, that only cleans up your code if you have several events manipulating the same variables that cause the form to need refreshing.
Taking into consideration your particular problem and the solutions posted, I would say the "cleanest" approach here would be to implement a Property Changed Notification just for internal use in the form i.e. you don't need to expose the event like in the MSDN example.
This way you could maintain an internal list of properties that you know will require the form to be refreshed e.g.
private List<string> _refreshProps = new List<string>();
private bool _showPriority;
public void Form()
{
_refreshProps.Add("ShowPriority");
... etc
}
// only implement properties like this that need some extra work done
public bool ShowPriority
{
get { return _showPriority; }
set
{
if (_showPriority != value)
{
_showPriority = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("ShowPriority");
}
}
}
// basic property that doesn't require anything extra
public bool AnotherProperty { get; set; }
public void Refresh()
{
// refresh the form
}
protected void OnPropertyChanged(string name)
{
if (_refreshProps.Contains(name))
Refresh();
}
The benefit of this approach is if in the future you needed to do other "stuff" after particular properties you can simply introduce another list and handle it again in your OnPropertyChanged method.
Don't call Refresh, call Invalidate. The mechanism you need is already built into Windows. Calling Invalidate simply makes a note that the window needs repainting. The operating system will eventually post a WM_PAINT message (typically after the root DispatchMessage call finishes, but the exact implementation is irrelevant).
Use a property that calls Refresh in the setter.
Something like this:
private void RefreshAfter(Action action)
{
action();
Refresh();
}
UPDATED TO MAKE IT MORE OBVIOUS:
private void DoSomeUiShiznit(Action action)
{
action();
// other parts of the code don't realize that Refresh has to be called.
// But that's cool. I got it covered.
Refresh();
}
private void PriorityLine_Click(object sender, EventArgs e)
{
DoSomeUiShiznit(() => { _showPriorityLine = !_showPriorityLine; });
}
UPDATE -- Just a message to the down-voters:
What some of you are too blind to see is that this is not all that different from:
[SomeRefreshAttribute]
private void PriorityLine_Click(object sender, EventArgs e)
{
_showPriorityLine = !_showPriorityLine;
}
Except that it is simpler, and doesn't require adding another framework to the solution. And yet the other answer suggesting as much don't get down-voted!
What's wrong with you people?
Let's say I created an object O on the thread T. How can I get, from inside object O the thread T and invoke a method on that thread?. This way, it won't be necessary for the form that created the object to to this:
private void ChangeProgress(int value)
{
progressBar1.Value = value;
}
void FD_ProgressChanged(object sender, DownloadEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<int>(ChangeProgress), new object[] { e.PercentDone });
}
else ChangeProgress(e.PercentDone);
}
which is just ugly and requires whoever uses the object to either figure out which events are raised on the same thread that created the object and which are not and add the if(InvokeRequired)...else code on the ones that are not, or just add the code on every single event handler. I think it would be more elegant if the object itself takes care of invoking the event on the right thread. Is this possible?
Use the BackgroundWorker class. It takes care of all this. Note the ReportProgress event.
You are going to have to track it yourself like
class Foo {
private readonly Thread creatingThread;
public Foo() {
this.creatingThread = Thread.CurrentThread;
}
}
If you don't do that, there is no way to know. But the fact that you are doing this is a smell. Consider using a BackgroundWorker.
There are a few thing you need to consider:
You will need to keep a reference in Object O of a thread that it was created in. Probably in a constructor using Thread.Current static property.
That thread will need to have a SynchronizationContext associated with it. (Generally, UI threads have it. And its not easy to create one for a custom thread you created.)
To invoke a method on that thread, you will need to use Send() or Post() methods on that thread's SynchronizationContext.
Found a nice solution at http://www.codeproject.com/KB/threads/invoke_other_way.aspx
And here's is my generic version:
private void RaiseEventAsync(Delegate handler, object e)
{
if (null != handler)
{
List<Delegate> invocationList = handler.GetInvocationList().ToList();
foreach (Delegate singleCast in invocationList)
{
System.ComponentModel.ISynchronizeInvoke syncInvoke =
singleCast.Target as System.ComponentModel.ISynchronizeInvoke;
try
{
if ((null != syncInvoke) && (syncInvoke.InvokeRequired))
syncInvoke.Invoke(singleCast,
new object[] { this, e });
else
singleCast.Method.Invoke(singleCast.Target, new object[] { this, e });
}
catch
{ }
}
}
}
And this is how you would use it:
protected void OnProgressChanged(DownloadEventArgs e)
{
RaiseEventAsync(ProgressChanged, e);
}
This takes care of my problem without needing to use a BackgroundWorker that is not always wanted (like on my case, where I'm subclassing a class that already uses a different threading object).