在另一个线程中循环ping +更新UI

时间:2019-04-16 09:13:44

标签: c# .net wpf multithreading

我正在实现循环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,但结果相同。

0 个答案:

没有答案