Personnellement, je préfère ne pas voir de pointeur de la souris de commutation à plusieurs reprises à partir de sablier à la flèche.
Pour prévenir l'apparition de ce comportement, tout en appelant intégré des fonctions qui prennent un certain temps et que chacun essaie de contrôler le pointeur de la souris, j'utilise une pile (compteur) que j'appelle une LifeTrackerStack. Et seulement quand la pile est vide (compteur à 0) que je fais revenir l'heure de verre d'une flèche.
J'utilise aussi MVVM. Je préfère aussi thread-safe code.
Dans ma classe racine de modèle je déclare mon LifeTrackerStack que je soit remplir dans l'enfant des classes de modèle ou utiliser directement à partir de modèle de l'enfant des classes lorsque j'ai accès à la leur.
Ma vie tracker avons 2 membres/actions:
- Vivant (compteur > 0) => tourner le Modèle.IsBusy true;
- Fait (compteur == 0) => tourner le Modèle.IsBusy false;
Alors de mon point de vue, j'ai manuellement lier à mon Modèle.IsBusy et à faire:
void ModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsBusy")
{
if (this._modelViewAnalysis.IsBusy)
{
if (Application.Current.Dispatcher.CheckAccess())
{
this.Cursor = Cursors.Wait;
}
else
{
Application.Current.Dispatcher.Invoke(new Action(() => this.Cursor = Cursors.Wait));
}
}
else
{
Application.Current.Dispatcher.Invoke(new Action(() => this.Cursor = null));
}
}
C'est ma classe LifeTrackerStack:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
namespace HQ.Util.General
{
/// <summary>
/// Usage is to have only one event for a recursive call on many objects
/// </summary>
public class LifeTrackerStack
{
// ******************************************************************
protected readonly Action _stackCreationAction;
protected readonly Action _stackDisposeAction;
private int _refCount = 0;
private object _objLock = new object();
// ******************************************************************
public LifeTrackerStack(Action stackCreationAction = null, Action stackDisposeAction = null)
{
_stackCreationAction = stackCreationAction;
_stackDisposeAction = stackDisposeAction;
}
// ******************************************************************
/// <summary>
/// Return a new LifeTracker to be used in a 'using' block in order to ensure reliability
/// </summary>
/// <returns></returns>
public LifeTracker GetNewLifeTracker()
{
LifeTracker lifeTracker = new LifeTracker(AddRef, RemoveRef);
return lifeTracker;
}
// ******************************************************************
public int Count
{
get { return _refCount; }
}
// ******************************************************************
public void Reset()
{
lock (_objLock)
{
_refCount = 0;
if (_stackDisposeAction != null)
{
_stackDisposeAction();
}
}
}
// ******************************************************************
private void AddRef()
{
lock (_objLock)
{
if (_refCount == 0)
{
if (_stackCreationAction != null)
{
_stackCreationAction();
}
}
_refCount++;
}
}
// ******************************************************************
private void RemoveRef()
{
bool shouldDispose = false;
lock (_objLock)
{
if (_refCount > 0)
{
_refCount--;
}
if (_refCount == 0)
{
if (_stackDisposeAction != null)
{
_stackDisposeAction();
}
}
}
}
// ******************************************************************
}
}
using System;
namespace HQ.Util.General
{
public delegate void ActionDelegate();
public class LifeTracker : IDisposable
{
private readonly ActionDelegate _actionDispose;
public LifeTracker(ActionDelegate actionCreation, ActionDelegate actionDispose)
{
_actionDispose = actionDispose;
if (actionCreation != null)
actionCreation();
}
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
_actionDispose();
}
// Note disposing has been done.
_disposed = true;
}
}
}
}
Et l'utilisation de celui-ci:
_busyStackLifeTracker = new LifeTrackerStack
(
() =>
{
this.IsBusy = true;
},
() =>
{
this.IsBusy = false;
}
);
Partout, j'ai de longues jogging, je fais:
using (this.BusyStackLifeTracker.GetNewLifeTracker())
{
// long job
}
Il fonctionne pour moi.
Espérons que cela pourrait les aider!
Eric