In my WPF application , the instantiation of the viewmodel classes takes a lot of time, so I think, to solve this issue, to create a static objects when I launch my application :
protected override void OnStartup(StartupEventArgs e)
{
ViewModelLocator locator = (ViewModelLocator)App.Current.Resources["Locator"];
LoginWindowViewModel.objFicheViewModel = locator.FicheViewModel;
LoginWindowViewModel.objFormationsViewModel = locator.FormationsViewModel;
LoginWindowViewModel.objFacturationViewModel = locator.FacturationViewModel;
LoginWindowViewModel.objGestionDPCViewModel = locator.GestionDPCViewModel;
LoginWindowViewModel.objGestionGDPViewModel = locator.GestionGDPViewModel;
}
So I need to know :
Is it a good solution?
How to improve it to make the instantiation work in a parallel way to avoid UI pause( the instantiation part takes 5 seconds!!)
You can make use of async and await to set up your ViewModels.
Consider this:
Create a property called IsSettingUp in your LoginWindowViewModel, like so:
private bool _IsSettingUp;
public bool IsSettingUp
{
get { return _IsSettingUp; }
set
{
_IsSettingUp = value;
//On property changed stuff
OnPropertyChanged();
}
}
Then create an async method responsible for creating your ViewModels.
public async void Setup()
{
this.IsSettingUp = true;
await SetupViewModels();
//Other initialization stuff here if needed
this.IsSettingUp = false;
}
And the SetupViewModels method would look something like this:
private async Task SetupViewModels()
{
await Task.Factory.StartNew(() =>
{
ViewModelLocator locator = (ViewModelLocator)App.Current.Resources["Locator"];
LoginWindowViewModel.objFicheViewModel = locator.FicheViewModel;
LoginWindowViewModel.objFormationsViewModel = locator.FormationsViewModel;
LoginWindowViewModel.objFacturationViewModel = locator.FacturationViewModel;
LoginWindowViewModel.objGestionDPCViewModel = locator.GestionDPCViewModel;
LoginWindowViewModel.objGestionGDPViewModel = locator.GestionGDPViewModel;
});
}
To make use of the IsSettingUp property, consider creating a control that will be visible if IsSettingUp is true. Perhaps a loading icon, or a screen overlay. This will ensure that the UI will remain responsive while your ViewModels are being created.
Related
I wonder if there's a better approach to load async data into a property. now I create an async function and raise a Task in the Get part of the property like this:
private ObservableCollection<CProyecto> prope;
public ObservableCollection<CProyecto> Prope
{
get
{
if (prope == null)
{
Task.Run(()=> LoadData()).Wait();
}
return proyectos;
}
set
{
prope = value;
RaisePropertyChanged();
}
}
async private Task LoadData()
{
Prope = await clsStaticClassDataLoader.GetDataFromWebService();
}
This approach works, but I don't like the use of .Wait, because that can freeze the screen if the service doesn´t respond fast.
Can you please guide me on this matter?
thanks in advance
The way I handled this was to start the process of loading the property when the object was constructed, but I did not await the result. Since the property notifies when it is populated, the bindings worked just fine. Essentially it works like this:
public class MyClass : INotifyPropertyChanged
{
private ObservableCollection<CProyecto> prope;
public ObservableCollection<CProyecto> Prope
{
get { return prope; }
set { prope = value; RaisePropertyChanged(nameof(Prope)); }
}
public MyClass()
{
// Don't wait or await. When it's ready
// the UI will get notified.
LoadData();
}
async private Task LoadData()
{
Prope = await clsStaticClassDataLoader.GetDataFromWebService();
}
}
This works very well, and does not cause any delays or stuttering in the UI. If you want the collection to never be null (a good practice IMO), you can pre-initialize the prope field with an empty collection.
I suggest you read my MSDN article on async MVVM data-binding. I have a library (github link) that provides a NotifyTask<T> type, which can be used as such:
public class MyClass : INotifyPropertyChanged
{
public NotifyTask<ObservableCollection<CProyecto>> Prope { get; private set; }
public MyClass()
{
// Synchronously *start* the operation.
Prope = NotifyTask.Create(LoadDataAsync());
}
async private Task<ObservableCollection<CProyecto>> LoadDataAsync()
{
return await clsStaticClassDataLoader.GetDataFromWebService();
}
}
Then your databinding would operate on Prope.Result.
The advantage of this approach is that you can also use databinding to hide/show busy indicators (Prope.IsNotCompleted), show controls when the data is available (Prope.IsSuccessfullyCompleted), and error notifications (Prope.IsFaulted / Prope.ErrorMessage).
Also, you can specify a non-null default value, if you wish:
Prope = NotifyTask.Create(LoadDataAsync(), new ObservableCollection<CProyecto>());
Your current implementation of the Prope property doesn't make much sense. It is pointless to execute the LoadData method on a background thread since you block the main thread anyway when you call Wait(). You might as well call Wait() directly on the task returned by the LoadData() method:
//BAD IMPLEMENTATION!
private ObservableCollection<CProyecto> prope;
public ObservableCollection<CProyecto> Prope
{
get
{
if (prope == null)
LoadData().Wait();
return proyectos;
}
set { prope = value; RaisePropertyChanged(); }
}
The above implementation is still a bad one. The getter of a property is not supposed to perform an asynchronous operation. You should read #Stephen Cleary's blog post on the subject: https://blog.stephencleary.com/2013/01/async-oop-3-properties.html
...and look into his NotifyTaskCompletion type in his AsyncEx library: https://github.com/StephenCleary/AsyncEx
This is probably a really basic question, please bear with me, I'm still very new to the world of WPF/C#.
I have a WPF app where I open a new window if a button is clicked.
The window is called Sync and all it does is instantiate a viewmodel class which contains some public properties that are bound to my view.
The viewmodel also instantiates a class containing a lot of business logic, this updates the ViewModel's bound properties, the aim being to update the content of my window.
This sort of works, but only when all of the (sometimes quite lengthy) processing is completed does the window load and the view is populated with the last value of the ViewModel's properties.
I think I'm missing something pretty basic here. How do I get my window to instantly load and then have the view update when any of the properties have changed? Should I be listening for a PropertyChanged event and then updating the view? Where do i do this? Within the view model's setter?
Here's some simplified code:
Calling my window from my main window's View Model
public void SyncAction()
{
Sync syncWindow = new Sync();
syncWindow.Show();
syncWindow.Activate();
}
The window
public partial class Sync : Window
{
public Sync()
{
InitializeComponent();
var viewModel = new SyncViewModel();
}
}
The view model
class SyncViewModel
{
private string _miscStatus = "";
public SyncViewModel()
{
var sync = new SyncLogic();
sync.SyncAll(this);
}
public string MiscStatus
{
get
{
return _miscStatus;
}
set
{
_miscStatus += value;
}
}
}
Some business logic
class SyncLogic
{
private ViewModel.SyncViewModel _syncViewModel;
public void SyncAll(ViewModel.SyncViewModel syncViewModel)
{
_syncViewModel = syncViewModel;
// lock our synctime
var syncTime = DateTools.getNow();
_syncViewModel.MiscStatus = "Sync starting at " + syncTime.ToString();
// Do lots of other stuff
_syncViewModel.MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
}
Bonus question: The way I'm updating the view from within my business logic (by passing in a reference to the viewmodel and updating its properties from there) seems a bit kludgy. I definitely want to keep the business logic separate, but am not sure how I can pass any output back out to the viewmodel. What would be a better way of doing this please?
Why do you care whether the update takes visual effect before or after the code finishes executing? The internal properties are updated immediately; any code that queries the UI will see the new values.
The only time the user will be able to perceive a difference between an update during execution vs after execution is if you have a long-running computation on the UI thread. Don't do that.
Instead, run the computation asynchronously with the UI, so that repaint messages can be processed meanwhile. You can do this using a background thread, but the new easier way with C# 4 and later is async. Because async is implemented using continuation messages to the UI thread, you don't need to synchronize data access or marshal UI access between threads. It just works, and very well. The only thing you need to do is to break your code into small enough chunks, each implemented as an async method, that you don't cause noticeable delay.
What I would do:
Don't do any heavy logic in the ViewModel constructor. Constructor should only initialize object and do nothing else. In your example, constructor should be empty.
public SyncViewModel()
{
}
SyncLogic should not be aware of the ViewModel. Introduce some other class to communicate input arguments and sync results. Let's say SyncArguments and SyncResult.
class SyncLogic
{
public SyncResult SyncAll(SyncArguments syncArgs)
{
var syncResult = new SyncResult();
// Do lots of other stuff
// populate syncResult
return syncResult;
}
}
Introduce a method in the viewmodel that should be called to do the "sync" logic, and make that method async. That way it's very easy to do the heavy stuff in the background and leave the UI thread to do the job it should do, draw the UI.
public async Task Sync()
{
// lock our synctime
var syncTime = DateTools.getNow();
MiscStatus = "Sync starting at " + syncTime.ToString();
var sync = new SyncLogic();
var syncArgs = new SyncArguments();
//populate syncArgs from ViewModel data
//call the SyncAll as new Task so it will be executed as background operation
//and "await" the result
var syncResults = await Task.Factory.StartNew(()=>sync.SyncAll(syncArgs));
//when the Task completes your execution will continue here and you can populate the
//ViewModel with results
MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
Make the button click event handler that creates and shows the window async, so you can call Sync method on the ViewModel
private void async Button_click(object sender, EventArgs e)
{
Sync syncWindow = new Sync();
var viewModel = new SyncViewModel();
syncWindow.DataContext = viewModel;
syncWindow.Show();
syncWindow.Activate();
await viewModel.Sync();
}
That will draw the Window without waiting on the Sync method. When the Sync taks completes, viewmodel properties will be populated from the SyncResult and the Bindings will draw them on screen.
Hope you get the idea, sorry if there are some errors in my code, not sure that it all compiles.
First, make sure to set the viewmodel as the view's DataContext:
public partial class Sync : Window
{
public Sync()
{
InitializeComponent();
var viewModel = new SyncViewModel();
DataContext = viewModel;
}
}
Second, you'll have to run the "sync" stuff on a background thread. This is easiest with the async+await keywords in .Net 4.5:
public async void SyncAll(ViewModel.SyncViewModel syncViewModel)
{
_syncViewModel = syncViewModel;
// lock our synctime
var syncTime = DateTools.getNow();
_syncViewModel.MiscStatus = "Sync starting at " + syncTime.ToString();
await Task.Factory.StartNew(() => {
// Do lots of other stuff
});
_syncViewModel.MiscStatus = String.Format("Sync finished at at {0}, total time taken {1}",
DateTools.getNow().ToString(), (DateTools.getNow() - syncTime).ToString());
}
With databinding your Window will automatically updated as long as it notified that properties it bound to has been changed. So what you need is implement INotifyPropertyChanged in the viewmodel and raise property changed event whenever binding source property value changed. For example:
public class SyncViewModel : INotifyPropertyChanged
{
private string _miscStatus = "";
public string MiscStatus
{
get{ return _miscStatus; }
set
{
_miscStatus += value;
OnPropertyChanged("MiscStatus");
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
In case somebody else comes across this issue in WPF, the solution described here is really simple and just worked fine for me. It uses an extension method to force an UIElement to be rendered:
public static class ExtensionMethods
{
private static Action EmptyDelegate = delegate() { };
public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
}
}
Then, simply use as:
private void SomeLongOperation()
{
// long operations...
// UI update
label1.Content = someValue;
label1.Refresh();
// continue long operations
}
}
Quoting the original author:
The Refresh method is the extension method that takes any UI element and then calls that UIElement's Dispatcher's Invoke method. The trick is to call the Invoke method with DispatcherPriority of Render or lower. Since we don't want to do anything, I created an empty delegate. So how come this achieves refresh functionality?
When the DispatcherPriority is set to Render (or lower), the code will then execute all operations that are of that priority or higher. In the example, the code already sets label1.Content to something else, which will result in a render operation. So by calling Dispatcher.Invoke, the code essentially asks the system to execute all operations that are Render or higher priority, thus the control will then render itself (drawing the new content). Afterwards, it will then execute the provided delegate (which is our empty method).
I have Mainpage.cs where I have method public void websocketRequestGetListOfUni() and then I have this class
public class RegisterResponseReceiverRegisterDevice : ResponseReceiver
{
public override void onResponseReceived(byte[] header, byte[] response)
{
RegisterResponse rr = RegisterResponse.ParseFrom(response);
var t = new MainPage();
t.websocketRequestGetListOfUni();
}
public override void onError() { }
}
public void websocketRequestGetListOfUni()
{
IntMessage req = IntMessage.CreateBuilder().SetValue(1).Build();
WebSocketClient.write(3, 7, req, new RegisterResponseReceiverGetListOfUni());
}
I want call method websocketRequestGetListOfUni() in class RegisterResponseReceiverRegisterDevice but when I call it I get at var t = new MainPage();
error
The application called an interface that was assigned to a different
thread.
I also try use
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => mymethoc);
but Dispather is not recognized. Any idea how call my method?
here is Mainpage for better understanding: https://www.dropbox.com/s/oz6qb0naa0u0for/Mainpage.cs.txt
var t = new MainPage(); is going to instanciate the page (including the UI part (which is instanciated by the Initialise call in MainPage constructor)) so it's a very bad idea to instanciate it just to get access to a method. I strongly sugest that you to reachitecture your code so that you don't need to do that. Particularly you should look at the MVVM patern.
If you still want to do that, you can use the following code to dispatch your method on the UI thread:
await CoreApplication.MainView.CoreWindow.RunAsync(CoreDispatcherPriority.Normal, () => mymethoc);
I have an object that takes a long time to be initialized. Therefore I the capability to Start Initializing on application startup. Any subsequent calls to methods on the class we need to have a delay mechanism that waits for the class to finish initialization.
I have a couple of potential solutions however I am not entirely satisfied with either of them. The first uses Task.Delay in a while loop and the second uses SemaphoreSlim but involves some unnecessary blocking. I feel this must be a fairly common requirement, can anybody provide some advice on how to best manage this?
Oh btw, this is a Metro application so we have limited API's
Here is the pseudocode:
public class ExposeSomeInterestingItems
{
private InitialisationState _initialised;
private readonly SemaphoreSlim _waiter =
new SemaphoreSlim(0);
public async Task StartInitialize()
{
if (_initialised == InitialisationState.Initialised)
{
throw new InvalidOperationException(
"Attempted to initialise ActiveTrackDown" +
"loads when it is already initialized");
}
_initialised =
InitialisationState.StartedInitialisation;
new TaskFactory().StartNew(async () =>
{
// This takes some time to load
this._interestingItems =
InterestingItemsLoader.LoadItems();
_waiter.Release();
_initialised = InitialisationState.Initialised;
});
}
public InterestingItem GetItem(string id)
{
DelayUntilLoaded();
DelayUntilLoadedAlternative();
}
private async Task DelayUntilLoaded()
{
if (_initialised == InitialisationState.NotInitialised)
{
throw new InvalidOperationException("Error " +
"occurred attempting to access details on " +
"ActiveTrackDownloads before calling initialise");
}
while (true)
{
if (_initialised == InitialisationState.Initialised)
{
return;
}
await Task.Delay(300);
}
}
private async Task DelayUntilLoadedAlternative()
{
if (_initialised == InitialisationState.NotInitialised)
{
throw new InvalidOperationException(
"Error occurred attempting to access details " +
"on ActiveTrackDownloads before calling initialise");
}
try
{
await _waiter.WaitAsync();
}
finally
{
_waiter.Release();
}
}
}
I think that a better design would be an asynchronous factory, where the calling code awaits the object creation and then receives a regular object instance.
Stealing liberally from Stephen Toub:
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Run(valueFactory)) { }
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Run(taskFactory)) { }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}
public static class ExposeSomeInterestingItemsFactory
{
public static AsyncLazy<ExposeSomeInterestingItems> Instance
{
get { return _instance; }
}
private static readonly AsyncLazy<ExposeSomeInterestingItems> _instance =
new AsyncLazy<ExposeSomeInterestingItems>(() => new ExposeSomeInterestingItems());
public static void StartInitialization()
{
var unused = Instance.Value;
}
}
public class ExposeSomeInterestingItems
{
public ExposeSomeInterestingItems()
{
// This takes some time to load
this._interestingItems = InterestingItemsLoader.LoadItems();
}
public InterestingItem GetItem(string id)
{
// Regular logic. No "delays".
}
}
...
var exposeSomeInterestingItems = await ExposeSomeInterestingItemsFactory.Instance;
var item = exposeSomeInterestingItems.GetItem("id");
That way, you keep the Single Responsibility Principle nicely:
AsyncLazy<T> combines Task<T> with Lazy<T> (so the instance is created asynchronously only when needed).
ExposeSomeInterestingItemsFactory contains construction logic.
ExposeSomeInterestingItems is only concerned with exposing interesting items, rather than having to pollute all its members with asynchronous delays.
Also, this solution is asynchronous throughout (no blocking), which is good (particularly for Metro apps).
Update, 2012-09-14: I've taken this code and cleaned it up and commented it on my blog.
You can use the Task<T> for this. This will take care of all the synchronisation for you and allows you to block untill the value is available:
private static Task<HeavyObject> heavyObjectInitializer;
// Call this method during application initialization
public static void Bootstrap()
{
heavyObjectInitializer = new Task<HeavyObject>(() =>
{
// creation of heavy object here
return new HeavyObject();
});
// Start running the initialization right now on a
// background thread. We don't have to wait on this.
heavyObjectInitializer.Start();
}
// Call this method whenever you need to use the object.
public static HeavyObject GetHeavyObject()
{
// Get the initialized object, or block untill this
// instance gets available.
return heavyObjectInitializer.Result;
}
Optionally, you can also query to see if the object is available or not:
public static bool IsHeavyObjectAvailable
{
get { return heavyObjectInitializer.IsCompleted; }
}
Put the method calls into a queue which you process when you finish initialising. Only put methods into the queue when you have not yet initialised.
You could move to a an event driven architecture where you application is in different states.
Initially the application moves into the Starting state. In this state HeavyObject is created using a background task. When the initialization is complete an event is fired. (You don't have to use an actual .NET event. You can use callbacks or something similar and frameworks like Reactive Extensions allows you to compose sequences of events.)
When all initialization events have fired you move into the Started state of your application. For an UI application this could modify the UI to enable some previously disabled operations.
Check this Prototype Pattern. Maybe it can help you
You only need to create your object once and clone it when you need another one.
I put "volatile" because it's only vaguely so.
I have a class which has a property called StopRequested. This flag can be set by other threads at any time, and needs to indicate to my code that it should stop what it's doing and exit (this is a Windows Service based process, and when Stop is called, all processing needs to clean up and stop).
I wish to create some other classes to do the actual brunt of the processing work, however these classes also have to be aware of the "stop" flag. You can't just pass the flag because it will pass a copy, and you can't pass properties as ref types.
So how do you propagate a property that might change at any time into other classes?
The only thing I can think of is to pass a reference to the parent class, but I dislike coupling the worker classes to the parent for one flag. Any suggestions would be appreciated.
EDIT:
Here's a basic example:
public class A
{
public bool StopRequested { get; set; }
private Worker = new Worker();
public void DoWork();
{
worker.DoWork();
}
}
public class Worker
{
public void DoWork()
{
while(!StopRequested)
{
....
}
}
}
You could have each of your worker classes have their own StopRequest property and then just set that whenever StopRequest is flagged.
private List<IStopable> WorkerClasses = new List< IStopable > ()
public Bool StopRequest{
get
{
return _stopRequest;
}
set
{
_stopReqest = value;
foreach (var child in WorkerClasses)
child.StopRequest = value;
}
}
Like Rubens said, use an event. What you described basically defines event to a T:
Propagate a property change to other classes.
There is actually a facility in .NET that provides this already, albeit in a generic way: INotifyPropertyChanged. This interface provides a single event, PropertyChanged, that allows a class to notify any listeners of any property change.
In your case, you could easily provide your own interface that is more specific:
interface IStopNotifier
{
event EventHandler StopRequested;
}
This interface would be implemented by your main work manager (whatever it is), and could propagate itself like so:
class WorkManager: IStopNotifier
{
public event EventHandler StopRequested;
protected void OnStopRequested()
{
if (StopRequested != null) StopRequested(this, new EventArgs());
}
public void StopAllWorkers()
{
OnStopRequested();
}
public Worker CreateWorker<T>()
where T: Worker
{
var worker = new T(this);
return worker;
}
}
class abstract Worker: IDisposable
{
public Worker(IStopNotifier stopNotifier)
{
stopNotofier.StopRequested += HandleStopRequested;
}
private IStopNotifier m_stopNotifier;
private bool m_stopRequested = false;
internal void HandleStopRequested(object sender, EventArgs e)
{
m_stopRequested = true;
}
public void Dispose()
{
m_stopNotifier.StopRequested -= HandleStopRequested;
}
}
Why don't to create an event to handle stop requests?