先日問題が発生しました。私はなぜそれが起こっているのか分かったが、私はそれを解決する方法を知らないので、私はそのような問題で実行したことがない。新しいDispatcherTimerは古いものと一緒に作成されますが、新しいものだけを実行する必要があります
私は、DashboardView(メインビュー)でDispatcherTimerがDashboardViewModelで起動されるアプリケーションを持っています。 Timerがチェックされると、データベースからデータが取得され、このリストはViewとViewModelの間でデータバインドされます。新しいデータベースが変更されたデータがあると、サウンドが再生されます。
ユーザーは他のビューに移動できます。ユーザーがDashboardViewに戻ると、DashboardViewModelが再度作成され、DispatcherTimerも作成されます。
今は2つのタイマーがあり、それらはTickイベントを起動し、ユーザーにとって混乱するシナリオを作成します。
これは今のアプリケーションで何が起こるかの私の観察である:
私のタイマーは毎分刻み。アプリケーションを起動すると、DashboardView#1が開きます。 DashboardViewModel#1が起動し、DispatcherTimer#1も起動します。
私は別のビューに切り替えて、データ(新しい電子メール)を更新するので、Timerがチェックされると、DashboardViewのリストが変更され、サウンドが再生されます。
Timer#1が30秒になると、新しく作成されたDashboardViewに切り替わり、View & ViewModel & Timer#2を作成します。 1分後、Timer#1は新しいデータがあり、DBを更新してサウンドを再生しますが、ビュー内のリストは更新されません。 #1よりも#2のビューが上に表示されているからです。そうでなければ、私はそれが爽やかであると言っているオーバーレイを見るだろうから、私は知っている。
View#2はViewModel#2にデータバインドされています。 Timer#1はViewModel#1を更新しました。そのため、View#1がView#2で置き換えられ/オーバーラップしているため、変更が表示されません。 タイマー#2が1分30秒後にタイマー#2がチェックし、DBからデータを取得し、タイマー#1によってDBがすでに最新の状態になっているときにサウンドを再生せず、新しい状態のデータを表示します。
(私は意味を成していることを願っています)
ので、TLDR:唯一の1がアクティブである必要がありながら、実行している2つのタイマーがあります(最新のもの、私は思います)。 これをどうすれば実現できますか?私は今それを持っているよう
はここDashboardViewModel(の一部)です。
namespace QRM.ViewModel
{
class DashboardListViewModel : INotifyPropertyChanged
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
DBServer dbServer = new DBServer();
#region Constructor
public DashboardListViewModel()
{
log.Info("Dashboard Initializing - Starting...");
MyObservableCollection<View_server> listDashboard = new MyObservableCollection<View_server>();
ListDashboard = dbServer.ReadDashboard();
listBoxCommand = new RelayCommand(() => SelectionHasChanged());
// Refresh to get all new emails, errors, etc.
GetListDashboard();
IsRefreshing = Visibility.Collapsed;
// Make a timer to renew the data in the Dashboard automatically.
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = Properties.Settings.Default.Timer_interval; // hours, minutes, seconds.
timer.Start();
//Receive the Notification sent after DashboardDetailsViewModel has handled the button commands, and call a respond method for the List.
App.Messenger.Register("RefreshServers", (Action)(() => GetListDashboard()));
App.Messenger.Register("ClearSelection", (Action)(() => SelectedServer = null));
App.Messenger.Register("ErrorSolved", (Action)(() => KeepSelection(selectedServer)));
App.Messenger.Register("WarningSound", (Action)(() => HasNewError = true));
log.Info("Dashboard Initializing - Done.");
}
#endregion
#region Get list dashboard
private void GetListDashboard()
{
HasNewError = false;
log.Info("Dashboard - Checking for Email...");
// The old Outlook class and methods
//EmailManager checkMail = new EmailManager();
//checkMail.GetEmail();
// First, check for mail.
IMAPManager checkMail = new IMAPManager();
checkMail.GetEmail();
log.Info("Dashboard - Checking for linked Errors...");
// Check if the emails have Errors linked to them. If not, add the Error from the Email to the DB
ErrorManager checkError = new ErrorManager();
checkError.GetNewErrors();
log.Info("Dashboard List - Starting...");
// Load the dashboard.
ListDashboard = dbServer.ReadDashboard();
System.Diagnostics.Debug.WriteLine("REFRESHED THE DASHBOARD");
log.Info("Dashboard List - Done.");
}
private void KeepSelection(View_server keepSelection)
{
GetListDashboard();
SelectedServer = keepSelection;
SelectionHasChanged();
}
#endregion
#region Timer
//This method runs every time the timer ticks.
private async void timer_Tick(object sender, EventArgs e)
{
log.Info("Dashboard - Refreshing...");
System.Diagnostics.Debug.WriteLine(">>Timer tick");
IsRefreshing = Visibility.Visible;
// To make sure the overlay is visible to the user, let it be on screen for at least a second (2x half a second)
await Task.Delay(500);
if (selectedServer != null)
{
KeepSelection(selectedServer);
}
else
{
GetListDashboard();
}
// 2nd half second.
await Task.Delay(500);
IsRefreshing = Visibility.Collapsed;
if (hasNewError == true)
{
System.Diagnostics.Debug.WriteLine("List has new error");
PlayWarningSound();
HasNewError = false;
}
else
{
System.Diagnostics.Debug.WriteLine("List has no new error");
HasNewError = false;
}
System.Diagnostics.Debug.WriteLine(">>End timer");
log.Info("Dashboard - Refreshed.");
}
#endregion
}
}
"ユーザーがDashboardViewに戻ると、DashboardViewModelが再度作成されます。"それをしないでください。代わりに、既存のビューモデルインスタンスを再利用します。また、新しいビューモデルのインスタンスを作成できない場合は、以前のインスタンスでタイマーを停止するようにしてください(例: 'IDisposable'を実装し、もちろん' Dispose() 'メソッドを呼び出して、タイマーを停止させます。 – Clemens
ああ。ビュー切り替えは別のソースから取得したものなので、ビュー(モデル)が作成および/または切り替えられた場所とその方法を調べるためには、そのコードを調べなければなりません。しかし、私はそれを理解することができると思う。 – Kailayla