我正在实现循环ping功能,其输出应反映在UI按钮的启用状态中(即,当ping结果!=成功时,应禁用按钮)。我将WPF与MVVM模型结合使用,因此我不与代码中的控件进行交互,而是使用绑定和通知机制。
问题如下:
以此类推。因此,仅在刷新UI视图时,数据点存储连接状态的值更改才不会反映在UI更改中。我在整个应用程序中都使用了相同的通知机制,并且工作正常。
我还尝试在DB类的构造函数中仅调用ping一次,然后在启动应用程序时网络打开时屏幕上的按钮变为活动状态,而当网络断开时屏幕上的按钮变为无效状态。因此,通知机制有效。
这是对工作站执行ping操作的代码:
public sealed class DB
{
Action _update= null;
Ping _ping;
Thread thread;
static bool result;
System.Runtime.CompilerServices.TaskAwaiter<PingReply> _pingAwaiter;
MachineState machineState;
private DB() //Constructor
{
machineState = GlobalData.Instance.gMachineState; //GlobalData is a Singleton
_ping = new Ping();
_update= Update;
thread = new Thread(new ThreadStart(CyclicTest));
thread.Start();
}
private void CyclicTest()
{
while (true)
{
Thread.Sleep(500);
_pingAwaiter = _ping.SendPingAsync(new IPAddress(new byte[] { 10, 10, 1, 11 }), 100).GetAwaiter();
_pingAwaiter.OnCompleted(Update);
}
}
private void UpdateConnectionStatus()
{
if (_pingAwaiter.GetResult().Status = IPStatus.Success)
result = true;
else
result = false;
machineState.DBLinkActive = result;
}
}
这是我要更新的数据模型属性的代码
public class MachineState : ObservableObject
{
bool _dbLinkActive;
public bool DBLinkActive
{
get => _dbLinkActive;
set
{
if (_dbLinkActive == value)
return;
_dbLinkActive = value;
NotifyPropertyChanged();
}
}
}
这是ObservableObject抽象类的NotifyPropertyChanged方法:
public abstract class ObservableObject : INotifyPropertyChanged
{
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这是负责设置按钮的启用状态(谓词)的代码
public sealed class UnfinishedOrdersVM : ObservableObject
{
private MachineState _machineStateData; //this is the same object as in DB class
private bool CanRefreshOrders()
{
return _machineStateData.DBLinkActive;
}
}
为什么会这样?
我已经知道,线程可能是问题所在。如果将MessageBox放在公共属性的_dbLinkActive = value;
行之前,则会使多个MessageBoexes依次显示-因为它停止执行调用线程,并且其中有很多显示出来,这证明有很多线程出现了。
我还尝试通过Invoke
方法将BeginInvoke
更改为NotifyPropertyChanged
,但结果相同。