Reputation: 27605
I am building a device emulator. When it starts, it takes some time for it to initialized. This would be logically represented by being turned on and going immediately to an "Initialization" state, and after some time it goes to "Ready" state.
I am using MVVM, so the ViewModel will for now represent all the device logic. Each of the possible states have a datatriggered style to be rendered by the View. If I just set the state when I build the viewmodel, the view renders with the correct appearance.
What I want to do is to create a "timeout state", that is, when some event occurs (starting the application, clicking a certain button), the device enters a state for a fixed time, and then falls back to the "ready", or "idle" state.
I thought about using Sleep, but sleep blocks the UI (so they say). So I think about using Threads, but I am not sure how to do it. This is what I have got so far:
using System.ComponentModel;
namespace EmuladorMiotool {
public class MiotoolViewModel : INotifyPropertyChanged {
Estados _estado;
public Estados Estado {
get {
return _estado;
}
set {
_estado = value;
switch (_estado) {
case Estados.WirelessProcurando:
// WAIT FOR TWO SECONDS WITHOUT BLOCKING GUI
// It should look like the device is actually doing something
// (but not indeed, for now)
_estado = Estados.WirelessConectado;
break;
}
RaisePropertyChanged("Estado");
}
}
public MiotoolViewModel() {
// The constructor sets the initial state to "Searching"
Estado = Estados.WirelessProcurando;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public enum Estados {
UsbOcioso,
UsbAquisitando,
UsbTransferindo,
WirelessNãoPareado,
WirelessPareado,
WirelessDesconectado,
WirelessProcurando,
WirelessConectado,
WirelessAquisitando,
DataLoggerOcioso,
DataLoggerAquisitando,
Erro,
Formatando
}
}
Upvotes: 2
Views: 1945
Reputation: 17388
Firstly having a Sleep / Async operation in a property (getter / setter) is considered bad-practice
Try this as a replacement for Sleep without blocking the UI thread:
Create a function to set Estado
to Estados.WirelessProcurando
Assuming WirelessProcurando
means Initialising and WirelessConectado
means Initialised
.net45:
private async Task SetWirelessProcurando(int milliSeconds) {
Estado = Estados.WirelessProcurando;
await Task.Delay(milliSeconds);
Estado = Estados.WirelessConectado;
}
The reason we have the function return a Task
vs void
is just to let the caller if required await
on this function if the logic demands it accordingly
If you cannot use await
:
private void SetWirelessProcurando(int milliSeconds) {
Estado = Estados.WirelessProcurando;
var tempTask = new Task
(
() => {
Thread.Sleep(milliSeconds);
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => Estado = Estados.WirelessConectado));
},
System.Threading.Tasks.TaskCreationOptions.LongRunning
);
tempTask.Start();
}
Now calling this function whenever you want to change the setter will immediately set the state to "Intiialising" and after the given milliSeconds
switch to the Initialised
state.
Upvotes: 1