Я пытаюсь запустить другую модель представления внутри события таймера. Когда я пропустил это событие таймера, кажется, что пусковая установка используется нормально. Однако, если запуск выполняется во время события, это не так. Может кто-нибудь посмотреть, где проблема?
using System.Timers;
using Caliburn.Micro.Xamarin.Forms;
using MyProject.Resources;
using System.Windows.Input;
using Xamarin.Forms;
using System.Diagnostics;
namespace MyProject.ViewModels
{
public class PairingDeviceViewModel : BaseScreen {
public INavigationService NavigationService { get; set; }
private Timer timer;
private const float MAX = 20;
private string percentage;
private float rate;
public float Rate { get => rate; set => Set(ref rate, value); }
public string Percentage { get => percentage; set => Set(ref percentage, value); }
protected override void OnInitialize()
{
base.OnInitialize();
timer = new Timer
{
Interval = MAX,
};
}
protected override void OnActivate()
{
base.OnActivate();
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
timer.Elapsed -= Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
Debug.WriteLine($"Timer_Elapsed");
Debug.WriteLine($"Rate {Rate}");
Rate++;
Percentage = string.Format(StringResources.PercentageNumber, Rate);
NotifyOfPropertyChange(() => Percentage);
if (Rate == MAX)
{
timer.Stop();
Debug.WriteLine($"navigation begins");
NavigationService.NavigateToViewModelAsync<ConfigurationListViewModel>();
}
Debug.WriteLine($"Timer_Elapsed END");
}
public ICommand SkipBluetoothScanning => new Command(() => {
timer.Stop();
NavigationService.NavigateToViewModelAsync<ConfigurationListViewModel>();
});
}
Итак, в моем методе Timer_elapsed
я вызываю NavigationService.NavigateToViewModelAsync<>..
, как только Rate
становится равным MAX
. Проблема с этим в том, что это условие Rate==MAX
вызывалось более одного раза.
Пожалуйста, смотрите файл журнала.
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Timer_Elapsed
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Rate 0
Timer_Elapsed END
Timer_Elapsed
Rate 11
Timer_Elapsed END
Timer_Elapsed
Rate 12
Timer_Elapsed END
Timer_Elapsed
Rate 13
Timer_Elapsed END
Timer_Elapsed
Rate 14
Timer_Elapsed END
Timer_Elapsed
Rate 15
Timer_Elapsed END
Timer_Elapsed
Rate 16
Timer_Elapsed END
Timer_Elapsed
Timer_Elapsed END
Rate 17
Timer_Elapsed
Rate 18
Timer_Elapsed END
Timer_Elapsed
Rate 19
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
navigation begins
Timer_Elapsed END
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
Timer_Elapsed END
Timer_Elapsed END
Timer_Elapsed END
Timer_Elapsed END
Timer_Elapsed END
Timer_Elapsed END
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
Timer_Elapsed END
Timer_Elapsed END
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
Timer_Elapsed END
Timer_Elapsed END
[InputMethodManager] HSIFW - flag : 0 Pid : 6116
Timer_Elapsed END
Является ли DispatcherTimer
лучшим решением для этой или другой функции?
Большое спасибо.
Я могу увеличить timer.interval. Это должно быть хорошо для меня. И поскольку Timer.Interval является числом с плавающей запятой, именно поэтому я также использовал Rate как число с плавающей запятой. У меня проблема в том, что условие `if (Rate == Max) вызывается много раз.
Спасибо Джейсон. Это единственная возможная причина, по которой NavigateToViewModelAsync
не вызывается?
нет. Возможно, вам придется использовать BeginInvokeOnMainThread()
Спасибо, я попробую.
Да, это так. Спасибо!
не могли бы вы отметить это как ответ, спасибо
На самом деле я также должен сделать это, чтобы сделать его полным. если (Math.Abs(Rate - MAX) < double.Epsilon). Пожалуйста, добавьте его в свое решение, чтобы я мог пометить его как ответ. Спасибо!
Вы имеете в виду следующее?
Понятно. Сделанный! Спасибо за помощь!
вы можете заблокировать поток, чтобы избежать дублирования выполнения, например:
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (this)
{
if (Math.Abs(Rate - MAX) < double.Epsilon){
//something you want to do
...
}
}
}
Спасибо, я попробую.
во-первых, сравнивать поплавки с "= = " рискованно. Если вы увеличиваете на 1, лучше использовать ints. Кроме того, интервал по умолчанию для таймера составляет 100 мс, действительно ли вам нужна такая степень детализации?