Mar232010

Improving performance of DataBinding, patience is gold

Published by eric at 7:33 AM under C#

I came across a performance problem lately. I have a WPF Smart Client application connected to a Dynamics CRM back end. At some point in my application I have add a lot of lines in a data table held by an ObservableCollection class. The problem was each time I add a line into the collection a CollectionChanged event was raised and that triggered the update of some other fields, approximately 10 in my case.

So when was doing batch update the screen freezes for way too much time. I found out the problem was the cascading effect of recalculating all the dependent fields every time I add a ne line in the collection, thanks to the new Visual Studio 2010 performance analysis tools.

In this scenario, I’m only interested to get the totals right when I do the last insert, all other intermediate values are useless. I didn’t wan to play with the data binding itself. I could have unbound the total calculation and have it rebound at the end but I didn’t. Instead I chose to delay the calculation with some kind of sliding expiration timer. Such a timer, set with a timeout of 10 ms, would be reset every time a new add would be made, so if I add a bunch of line in batch odds that the delay between two line add be less than 10 ms is good. In fact it is so good that because it’s almost always true the calculation happens only once at the end.

So there is this magic DelayRun class with its DelayController:

using System;
using System.Collections.Generic;
using System.Threading;

namespace Infrastructure
{
    public interface IDelayRun
    {
        void Reset();
        void Start(int ms);
        event EventHandler<DelayRunEventArgs> EventCompleted;
    }

    public class DelayRun<T> : IDisposable, IDelayRun
    {
        private static readonly ManualResetEvent _resetEvent = new ManualResetEvent(true);
        private readonly Action<T> _action;
        private readonly T _target;
        private int _delay;
        private volatile Timer _timer;

        private DelayRun(T target, Action<T> action)
        {
            _action = action;
            _target = target;
        }

        #region IDelayRun Members

        public void Start(int ms)
        {
            if (ms == 0)
                throw new ArgumentOutOfRangeException("ms", ms, "ms should be grater than 0.");

            if (_delay != 0)
                throw new InvalidOperationException("Can't start, already started.");

            _delay = ms;
            _timer = new Timer(Execute, this, _delay, Timeout.Infinite);
        }

        public void Reset()
        {
            lock (_timer)
            {
                if (_timer == null)
                    throw new InvalidOperationException("Can't reset the timer, already completed.");

                _timer.Change(_delay, Timeout.Infinite);
            }
        }

        #endregion

        public static DelayRun<T> CreateNew(T target, Action<T> action)
        {
            return new DelayRun<T>(target, action);
        }

        public static DelayRun<T> StartNew(T target, Action<T> action, int ms)
        {
            DelayRun<T> delayRun = CreateNew(target, action);
            delayRun.Start(ms);
            return delayRun;
        }

        public void Execute(object state)
        {
            _resetEvent.WaitOne();
            lock (_timer)
            {
                _timer.Change(Timeout.Infinite, Timeout.Infinite);
            }

            _action.Invoke(_target);
            _resetEvent.Set();
        }

        #region Event Handling

        public event EventHandler<DelayRunEventArgs> EventCompleted;

        public void InvokeEventCompleted(DelayRunEventArgs e)
        {
            EventHandler<DelayRunEventArgs> handler = EventCompleted;
            if (handler != null) handler(this, e);
        }

        #endregion

        #region IDisposable

        public void Dispose()
        {
            lock (_timer)
            {
                if (_timer != null)
                    _timer.Dispose();
            }
        }

        #endregion
    }

    public class DelayRunEventArgs : EventArgs
    {
        public DelayRunEventArgs(IDelayRun delayAction)
        {
            DelayAction = delayAction;
        }

        public IDelayRun DelayAction { get; set; }
    }

    public static class DelayController
    {
        private static readonly IDictionary<string, IDelayRun> _actions = new Dictionary<string, IDelayRun>();

        public static void Add<T>(string key, T target, Action<T> action, int ms)
        {
            if (_actions.ContainsKey(key))
                _actions[key].Reset();
            else
            {
                DelayRun<T> delayRun = DelayRun<T>.CreateNew(target, _ => {});
                _actions[key] = delayRun;
                string localKey = key;
                delayRun.EventCompleted += (sender, args) =>
                {
                    _actions.Remove(localKey);
                    action.BeginInvoke(target, ar => ar.AsyncWaitHandle.WaitOne(), delayRun);
                };
                delayRun.Start(ms);
            }
        }
    }
}

To use this class all you need to do is call the DelayController. The DelayController will handle the creation and the reset process of the DelayRun class. It can handle many delay class at once if they have different key value. Each time the controller Add method is called it either create a new instance of a DelayRun Class of reset the running one.

Here is how you can call it:

DelayController.Add("ValuesOnCollectionChanged", this, m => Recalc(m), 10);

This call will delay the Recalc method call for 10 ms. In the mean time if your program add other values to recalc you can recall this line and the delay will be reset for another 10 ms and so on.

Tell me if this can be helpful in your own projects.



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 0 Responses

Mar182010

How to use strongly-typed name with INotifyPropertyChanged

Published by eric at 8:20 AM under .NET Framework | C# | Windows | WPF

You may already have read my posts about how to use INotifyPropertyChanged in a type-safe way (here and here), but sometime you don’t want to modify all your classes to use this method. All you want is avoid the use of a magic string to define the property. Your code will be refactoring proof.

For example let say you have this property:

public string FirstName
{
    get { return _firstName; }
    set 
    {
        if (_firstName == value)
            return;
        _firstName = value;
        RaisePropertyChanged("FirstName");
    }
}

Some refactoring tool, like Resharper, will be able to change the “FirstName” string but not Visual Studio itself. The solution? Replace this string with a strong type value. How? Let’s assume we can do this:

public string FirstName
{
    get { return _firstName; }
    set 
    {
        if (_firstName == value)
            return;
        _firstName = value;
        RaisePropertyChanged(this.NameOf(p => p.FirstName));
    }
}

Notice that you must specify the “this” keyword to make it work. That is exactly What this extension method let you do:

public static class ObjectExtensions
{
    public static string NameOf<T>(this T target, Expression<Func<T, object>> propertyExpression)
    {
        MemberExpression body = null;
        if (propertyExpression.Body is UnaryExpression)
        {
            var unary = propertyExpression.Body as UnaryExpression;
            if (unary.Operand is MemberExpression)
                body = unary.Operand as MemberExpression;
        }
        else if (propertyExpression.Body is MemberExpression)
        {
            body = propertyExpression.Body as MemberExpression;
        }
        if (body == null)
            throw new ArgumentException("'propertyExpression' should be a member expression");

        // Extract the right part (after "=>")
        var vmExpression = body.Expression as ConstantExpression;

        // Extract the name of the property to raise a change on
        return body.Member.Name;
    }
}

You can event use it in your property changed handler:

private void OnPropertyChanged(object sender, PropertyChangedEventArgs args)
{
    if (args.PropertyName == this.NameOf(p => p.FirstName))
    {
        // ...
    }
}

Enjoy!



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 0 Responses

Nov172009

SharePoint, Execution Context & Security

Published by Nicolas at 10:01 AM under C# | SharePoint 2007

At least once in his career, a SharePoint developer is going to be faced with a security problem.

When a user executes an action in SharePoint, i.e. modifies an item in a list, the request on the server executes using the security context of the user. So, if the user does not have the right privileges to accomplish specific actions, the request could fail with a security exception.

A way to overcome this behaviour is to use the RunWithElevatedPrivileges method from the SPUtility class.

An important thing to keep in mind when using this method is the initial context of the object on which you will execute specific actions.

In the example below, even if you use the RunWithElevatedPrivileges method, the security context of the SPWeb object (web variable) is inherited from the user permissions.
This behaviour is normal because the SPSite site variable is a reference to the properties variable which was created with the user’s security context.

public override void ItemUpdated(SPItemEventProperties properties)
{
	SPSecurity.RunWithElevatedPrivileges(delegate(){
		using (SPSite site = properties.ListItem.Web.Site)
		{
			using (SPWeb web = site.RootWeb)
			{
				web.AllowUnsafeUpdates = true;
                                // Do some actions
			}
		}
	});
}

To run in a context with full control, all objects should be instantiated inside the RunWithElevatedPrivileges delegate method.
By doing this, objects will inherit their permission from the RunWithElevatedPrivileges context which is full control:

public override void ItemUpdated(SPItemEventProperties properties)
{
	SPSecurity.RunWithElevatedPrivileges(delegate(){
		using (SPSite site = new SPSite(properties.ListItem.Web.Site.ID))
		{
			using (SPWeb web = site.RootWeb)
			{
				web.AllowUnsafeUpdates = true;
                                // Do some actions
			}
		}
	});
}


[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 1 Responses

Oct022009

Using Decorator (or Wrapper) Design Patterns to add Validation to an object

Published by eric at 9:40 AM under .NET Framework | C#

Context

In most cases when someone write about the Decorator pattern it is usually related to UI stuff. The most common example is adding “decoration” to a control, for example a scroll bar. But in my humble opinion, this is not the most useful usage of Decorator. The purpose this pattern is:

“Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality”

Gang of Four

If you think about it, Validation is a responsibility and so it can be added by this pattern. Of course we can add the validation to the class itself or in its base class, but how would you reuse this validation across many unrelated objects and what if you object must derive from another base class?

Solution

Decorator The solution is the Decorator pattern. With this pattern we can add new responsibility to an object without changing its internals.

For simplicity purpose we will take a simple sample that anyone can understand but the concept shown here can apply to much more complex object.

Four our sample we will take a bank account. On this account we should be able to to money deposit and withdraw. The class diagram on the right illustrate this design.

Let’s start by defining our IAccount interface

namespace Model
{
    public interface IAccount {
        string AccountNumber { get; }
        decimal Balance { get; }
        bool Active { get; }
        void Deposit(decimal amount);
        void Withdraw(decimal amount);
        void Close();
    }
}

This simple interface will be the central abstraction of the system. The goal is to never depends on concrete class and this interface in enough to add a lot of functionality around an account.

Now here the interface implementation as an Account:

using System.Diagnostics;

namespace Model
{
    [DebuggerDisplay("Account = {_accountNumber}, Balance = {_balance}")]
    public class Account : IAccount
    {
        public string AccountNumber { get; private set; }
        public decimal Balance { get; private set; }
        public bool Active { get; set; }

        internal Account(string accountNumber, decimal balance)
        {
            AccountNumber = accountNumber;
            Balance = balance;
            Active = true;
        }

        public void Deposit(decimal amount)
        {
            if (OnBeforeDeposit())
                Balance += amount;
            OnAfterDeposit();
        }

        protected virtual bool OnBeforeDeposit()
        {
            return true;
        }

        protected virtual void OnAfterDeposit() { }

        public void Withdraw(decimal amount)
        {
            if (OnBeforeWithdraw())
                Balance -= amount;
            OnAfterWithdraw();
        }

        protected virtual bool OnBeforeWithdraw()
        {
            return true;
        }

        protected virtual void OnAfterWithdraw() { }

        public void Close()
        {
            if (OnBeforeClose())
                Active = false;
            OnAfterClose();
        }

        protected virtual bool OnBeforeClose()
        {
            return true;
        }

        protected virtual void OnAfterClose() { }
    }
}

If you expand the previous block of code you will see that the implementation of IAccount is only doing business stuff. There is no other responsibility in this class than the one that is meant for. We can clearly see “Template Method” design pattern here. All “OnSomething()” method are protected and any derided class can add implementation around the process. All “Before” method can cancel the process if the return value is false. This allow extension classes to add some specific behaviour.

But one of the main thing missing in this class is “validation”. We will use the decorator pattern to do that. A decorator class is a class thst implement all the member of an abstraction and forward all the calls to an internal instance of a real implementation that abstraction. In our case the abstraction is “IAccount” so we have to make a decorator that implement that interface.

namespace Model.Decorator
{
    public abstract class AccountDecorator : IAccount
    {
        private readonly IAccount _account;

        protected IAccount Account
        {
            get { return _account; }
        }

        protected AccountDecorator(IAccount account)
        {
            _account = account;
        }

        public string AccountNumber
        {
            get { return Account.AccountNumber; }
        }

        public decimal Balance
        {
            get { return Account.Balance; }
        }

        public bool Active
        {
            get { return Account.Active; }
        }

        public virtual void Deposit(decimal amount)
        {
            Account.Deposit(amount);
        }

        public virtual void Withdraw(decimal amount)
        {
            Account.Withdraw(amount);
        }

        public virtual void Close()
        {
            Account.Close();
        }
    }
}

As you can see the constructor of the decorator takes an instance of “IAccount”. All method forward their call to that instance. This base class simplifies the process of creating concrete decorator by allowing other decorator to implement some but not all members of the interface.

Now is the time to start implementing our validation class structure. For that purpose we will create a base validation class that will be responsible of applying the validation the IAccount instance.

using System.Collections.Generic;
using Model.Decorator;

namespace Model.Validator
{
    public abstract class AccountValidatorBase : AccountDecorator
    {
        protected abstract IEnumerable<IValidation> GetValidations(decimal amount);

        protected AccountValidatorBase(IAccount account) : base(account) {}

        protected void Validate(decimal amount)
        {
            foreach (var validation in GetValidations(amount))
                if (!validation.IsValid)
                    throw validation.Exception;
        }
    }
}

This simple base class define a “GetValidations” method that all derived class must override to add a list of validation to perform on method call.

Now to implement the “Deposit” validation we have to create this class:

using System.Collections.Generic;
using Model.Validation;

namespace Model.Validator
{
    public class AccountDepositValidator : AccountValidatorBase
    {
        public AccountDepositValidator(IAccount account) : base(account) {}

        protected override IEnumerable<IValidation> GetValidations(decimal amount)
        {
            return new List<IValidation>
            {
                new AmountGreaterThanZeroValidation(amount),
                new AmountShouldHaveOnlyTwoDecimals(amount),
                new AccountMustBeActiveValidation(Account),
                new DepositAmountNotExceedMaxValidation(Account, amount)
            };
        }

        public override void Deposit(decimal amount)
        {
            Validate(amount);
            Account.Deposit(amount);
        }
    }
}

This class is responsible for creating all validation instances. The “Deposit” method is overridden to call the base “Validate” method before doing the actual deposit.

To implement those validation we need to define the “IValidation” interface.

using System;

namespace Model.Validator
{
    public interface IValidation 
    {
        bool IsValid { get; }
        Exception Exception { get; }
    }
}

Here is a sample implementation:

using System;
using Model.Validator;

namespace Model.Validation
{
    public class AmountGreaterThanZeroValidation : IValidation
    {
        public AmountGreaterThanZeroValidation(decimal amount)
        {
            Amount = amount;
        }

        public decimal Amount { get; set; }

        public bool IsValid
        {
            get { return Amount > 0; }
        }

        public Exception Exception
        {
            get { return new ArgumentOutOfRangeException("amount", Amount, "Deposit amount should be greater than 0."); }
        }
    }
}

All other validations used in “AccountDepositValidator” can be described the same way.

The last step is to create an actual “IAccount” that will implement all this stuff. To do that we will need a Bank class. A bank is responsible of creating account. It will also be responsible of decorating it with all necessary decorators.

using System;
using System.Collections.Generic;
using Model.Logging;
using Model.Validator;

namespace Model
{
    public static class Bank
    {
        static readonly SortedDictionary<string, IAccount> _accounts = new SortedDictionary<string, IAccount>();
        private static int _accountSequence = 1;

        public static IAccount CreateAccount(decimal balance)
        {
            string accountNumber = String.Format("A{0:0000}", _accountSequence++);
            IAccount account = new Account(accountNumber, balance);
            account = new AccountDepositValidator(account);
            _accounts[account.AccountNumber] = account;
            return account;
        }
    }
}

To illustrate this process in action here is a sequence diagram:

Validation with Decorator

  1. Call Bank.CreateAccount.
  2. The Bank instantiate an Account class.
  3. The Bank create an AccountDepositValidator and wrap Account with it
  4. The Bank return an instance of IAccount.
  5. Deposit is called on IAccount which is an instance of AccountDepositValidator
  6. AccountDepositValidator call Validate
  7. AccountDepositValidator call GetValidations to retrieve the list of validation to evaluate
  8. An AmountGreaterThaZeroValidation is created
  9. IsValid returns true
  10. AccountDepositValidator call base Deposit method
  11. Balance value is updated

Next

With all this in place the only thing left to do is to implement all the other validators for all method of “IAccount”.



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 1 Responses

Jul272009

Type-safe INotifyPropertyChanged and derived classes

Published by eric at 7:50 AM under .NET Framework | C# | Windows | WPF

Some of you who read my previous blog post notice that this technique doesn't allow to raise “PropertyChanged” event from a derived class. This is because you can only call method of “PropertyChangedEventHandler” from the class where it is defined. Anywhere else you can only assign (+=) and unassign (-=) event handler.

One way to work around this is to add a method in your base model class that will forward the call to “PropertyChangedEventHandler”.

Here is a modified copy of the class from my previous post:

public class Model : INotifyPropertyChanged
{
    private string _data;

    public string Data
    {
        get { return _data; }
        set
        {
            if (_data == value)
                return;

            _data = value;

            // Type safe raise from base method
            RaisePropertyChanged(() => Data);
        }
    }

    protected void RaisePropertyChanged(Expression<Func<object>> expression)
    {
        PropertyChanged.Raise(expression);   
    }

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged = null;

    #endregion
}

Now you can define a derived class and use the same method to raise a PropertyChanged event.

public class DerivedModel : Model
{
    private string _moreData;

    public string MoreData
    {
        get { return _moreData; }
        set
        {
            if (_moreData == value)
                return;

            _moreData = value;
            RaisePropertyChanged(() => MoreData);
        }
    }
}

Now with very little effort you can build a type-safe and bindable data model.

It is also useful to be able to raise many property at once. For example if have calculated properties that depends on others like in this sample class:

public class User : INotifyPropertyChanged
{
    private string _lastName;

    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (_lastName == value)
                return;

            _lastName = value;
            RaisePropertyChanged(()=>LastName, ()=>FullName);
        }
    }

    private string _firstName;

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (_firstName == value)
                return;

            _firstName = value;
            RaisePropertyChanged(() => FirstName, () => FullName);
        }
    }

    public string FullName
    {
        get { return String.Format("{0} {1}", _firstName, _lastName); }
    }

    public void RaisePropertyChanged(params Expression<Func<object>>[] expression)
    {
        PropertyChanged.Raise(expression);
    }

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged = null;

    #endregion
}

Because a change to either “FirstName” or “LastName” should trigger a change to “FullName” you have to raise both changes from both properties. Of course you can call “RaisePropertyChanged” many times but with a simple overload you can do this. All you have to do is add this to your extensions class.

public static void Raise(this PropertyChangedEventHandler handler, params Expression<Func<object>>[] proppertyExpressions)
{
    foreach (var expression in proppertyExpressions)
        Raise(handler, expression);
}

Aside from beeing type safe, this method will give you intellisense support while you type your “RaiePropertyChanged” calls. You still have to type the right property though.



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 2 Responses

Jul222009

How to use INotifyPropertyChanged, the type-safe way (no magic string)

Published by eric at 10:43 PM under .NET Framework | C# | Windows | WPF

Implementation of the INotifyPropertyChanged interface is quite simple. There is only one event to implement. Take for example the following simple model class:

public class Model : INotifyPropertyChanged
{
    private string _data;

    public string Data
    {
        get { return _data; }
        set
        {
            if (_data == value)
                return;

            _data = value;

            // Type un-safe PropertyChanged raise 
            PropertyChanged(this, new PropertyChangedEventArgs("Data"));
        }
    }

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged = null;

    #endregion
}

This is a pretty standard way to implement a bindable property. The problem here is the “Data” string to specify which property changed. If someone change the name of the property without changing the content of the string, the code will compile fine but won’t work. In a big application with may properties it can be hard to detect and find the problem.

The best solution is to rely on the compiler to warn us. But because the property name is a string it can’t. So let’s change that line with a type-safe one.

public class Model : INotifyPropertyChanged
{
    private string _data;

    public string Data
    {
        get { return _data; }
        set
        {
            if (_data == value)
                return;

            _data = value;

            // Type safe PropertyChanged raise
            PropertyChanged.Raise(() => Data);
        }
    }

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged = null;

    #endregion
}

What is the trick? Raise is an extension method that takes a lambda expression to specify the name of the property in a type safe way. The Raise method resolve this expression to extract the name of the property and pass it to the PropertyChanged event.

public static class PropertyChangedExtensions
{
    public static void Raise(this PropertyChangedEventHandler handler, Expression<Func<object>> propertyExpression)
    {
        if (handler != null)
        {
            // Retreive lambda body
            var body = propertyExpression.Body as MemberExpression;
            if (body == null)
                throw new ArgumentException("'propertyExpression' should be a member expression");

            // Extract the right part (after "=>")
            var vmExpression = body.Expression as ConstantExpression;
            if (vmExpression == null)
                throw new ArgumentException("'propertyExpression' body should be a constant expression");

            // Create a reference to the calling object to pass it as the sender
            LambdaExpression vmlambda = Expression.Lambda(vmExpression);
            Delegate vmFunc = vmlambda.Compile();
            object vm = vmFunc.DynamicInvoke();

            // Extract the name of the property to raise a change on
            string propertyName = body.Member.Name;
            var e = new PropertyChangedEventArgs(propertyName);
            handler(vm, e);
        }
    }
}

All you have to do is to put this extension method in your code and the jib is done. Of course at the end a string will be used to raise the PropertyChanged event but because you don’t have to type it, you don’t have to maintain it.



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 0 Responses

Mar262009

Good practice to use Dispatcher in WPF background thread

Published by eric at 10:51 AM under .NET Framework | C# | WPF

Here is a good way to use extension method in a multi threaded context. Everybody knows that when you try to update UI from any other thread than the UI you get an “InvalidOperationException” with message “The calling thread cannot access this object because a different thread owns it.”. Look at the following sample:

Let say somewhere in your code you have this

private void Button_Click(object sender, RoutedEventArgs e)
{
    // ...
    ThreadPool.QueueUserWorkItem(DoWork, this);
    // ...
}

If you implement DoWork Like this…

private static void DoWork(object state)
{
    Window1 win = (Window1) state;
    for (int i = 0; i < 100; i++)
    {
        // do some work
        win.progress1.Value = i;
    }
    win.progress1.Value = 100;
}

…you will be in trouble.

   

Because you can’t update UI from a thread other than the UI one you will get the InvalidOperationException as stated before.

The solution is to use the Dispatcher object. As from microsoft documentation:

Only the thread that the Dispatcher was created on may access the DispatcherObject directly. To access a DispatcherObject from a thread other than the thread theDispatcherObject was created on, call Invoke or BeginInvoke on the Dispatcher the DispatcherObject is associated with.

Subclasses of DispatcherObject that need to enforce thread safety can do so by calling VerifyAccess on all public methods. This guarantees the calling thread is the thread that theDispatcherObject was created on.

So our previous sample should look like this:

private static void DoWork(object state)
{
    Window1 win = (Window1) state;
    for (int i = 0; i < 100; i++)
    {
        // do some work
        win.Dispatcher.Invoke(new Action<ProgressBar, int>((p, v) => p.Value = v), win.progress1, i);
    }
    win.Dispatcher.Invoke(new Action<ProgressBar>(p => p.Value = 100), win.progress1);
}
This is a little more work but not it works. Because we don’t want to call the Dispatcher object when it’s not needed we sould do this:
private static void DoWork(object state)
{
    Window1 win = (Window1) state;
    for (int i = 0; i < 100; i++)
    {
        // do some work
        if (win.Dispatcher.CheckAccess())
            // We can call on the current thread
            win.progress1.Value = i;
        else
            // we need to call Invoke
            win.Dispatcher.Invoke(new Action<ProgressBar, int>((p, v) => p.Value = v), win.progress1, i);
    }

    if (win.Dispatcher.CheckAccess())
        // We can call on the current thread
        win.progress1.Value = 100;
    else
        // we need to call Invoke
        win.Dispatcher.Invoke(new Action<ProgressBar>(p => p.Value = 100), win.progress1);
}
Ouch! This is a lot more work. We cannot do that every time. That’s when extensions method comes handy. We can replace this whole process of choosing the right implementation with a single extension method. It will make our code more readable and more manageable.

 

 

He is the whole extension class with all possible overload for a method called Dispatch. This method will dispatch the process only if needed:

public static class DispatcherExtensions
{
    public static TResult Dispatch<TResult>(this DispatcherObject source, Func<TResult> func)
    {
        if (source.Dispatcher.CheckAccess())
            return func();

        return (TResult) source.Dispatcher.Invoke(func);
    }

    public static TResult Dispatch<T, TResult>(this T source, Func<T, TResult> func) where T : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            return func(source);

        return (TResult)source.Dispatcher.Invoke(func, source);
    }

    public static TResult Dispatch<TSource, T, TResult>(this TSource source, Func<TSource, T, TResult> func, T param1) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            return func(source, param1);

        return (TResult)source.Dispatcher.Invoke(func, source, param1);
    }

    public static TResult Dispatch<TSource, T1, T2, TResult>(this TSource source, Func<TSource, T1, T2, TResult> func, T1 param1, T2 param2) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            return func(source, param1, param2);

        return (TResult)source.Dispatcher.Invoke(func, source, param1, param2);
    }

    public static TResult Dispatch<TSource, T1, T2, T3, TResult>(this TSource source, Func<TSource, T1, T2, T3, TResult> func, T1 param1, T2 param2, T3 param3) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            return func(source, param1, param2, param3);

        return (TResult)source.Dispatcher.Invoke(func, source, param1, param2, param3);
    }

    public static void Dispatch(this DispatcherObject source, Action func)
    {
        if (source.Dispatcher.CheckAccess())
            func();
        else
            source.Dispatcher.Invoke(func);
    }

    public static void Dispatch<TSource>(this TSource source, Action<TSource> func) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            func(source);
        else
            source.Dispatcher.Invoke(func, source);
    }

    public static void Dispatch<TSource, T1>(this TSource source, Action<TSource, T1> func, T1 param1) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            func(source, param1);
        else
            source.Dispatcher.Invoke(func, source, param1);
    }

    public static void Dispatch<TSource, T1, T2>(this TSource source, Action<TSource, T1, T2> func, T1 param1, T2 param2) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            func(source, param1, param2);
        else
            source.Dispatcher.Invoke(func, source, param1, param2);
    }

    public static void Dispatch<TSource, T1, T2, T3>(this TSource source, Action<TSource, T1, T2, T3> func,
                                                     T1 param1, T2 param2, T3 param3) where TSource : DispatcherObject
    {
        if (source.Dispatcher.CheckAccess())
            func(source, param1, param2, param3);
        else
            source.Dispatcher.Invoke(func, source, param1, param2, param3);
    }
}

That seems a lot of code to write but see how it simplifies the code when you use it:

private static void DoWork(object state)
{
    Window1 win = (Window1) state;
    for (int i = 0; i < 100; i++)
    {
        // do some work
        win.progress1.Dispatch((p, v) => p.Value = v, i);
    }

    win.progress1.Dispatch(p => p.Value = 100);
}

This is almost as simple as our first implementation of DoWork. The only difference is in this version we call “Dispatch” with a lambda expression that will always be run on the UI thread.

 

 

Let me know if you find this helpful or if you think of something better.



[KickIt] [Dzone] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Tags: , , , ,

E-mail | Permalink | Trackback | Post RSSRSS comment feed 1 Responses