为什么此代码在由计时器执行时不起作用,而在其他地方调用时却可以正常工作?

时间:2019-08-22 15:15:02

标签: c# wpf

我正在使用数据供应商提供的API将数据提取到C#/ WPF应用程序中。我的连接工作正常,数据正在拉出。我进行了检查,以定期验证该连接没有丢失,如果发生这种情况,请重新连接。该检查由计时器执行,但由于某些原因它无法调用,即使它与在我的应用程序中其他任何地方调用的代码相同也可以工作。

我认为这与一个单例实例和计时器是一个单独的线程有关。但我不确定如何解决。

在InitializeComponent之后被调用

Range

事件处理程序OnStateChanged和timeSeries_ServiceInformationChanged只是更新UI以向用户显示连接状态。

这4行代码在启动时或通过“重新连接”按钮或类似的方式从UI调用时都可以正常运行,即使我这样使用lock关键字,也不能通过经过的计时器事件:

public void OpenConnections()
{
    DataServices.Instance.StateChanged += OnStateChanged;
    DataServices.Instance.Initialize(AppName);
    _timeSeries = DataServices.Instance.TimeSeries;
    _timeSeries.ServiceInformationChanged += 
    timeSeries_ServiceInformationChanged;
}

编辑:

这是根据要求的计时器代码。

private static readonly object padlock = new object();

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    if (DataServices.Instance.State == DataServicesState.Up && 
        _timeSeries.ServiceInformation.State == ServiceState.Up)
    {
        //do nothing, services are up and connected.
    }
    else
    {
        lock(padlock)
        {
            OpenConnections();
        }
    }
}

然后在InitalizeComponent()之后调用InitializeConnectionCheckerTimer()

编辑#2 我知道了。问题是线程问题,API将仅从创建它的UI线程进行连接。我不确定为什么会这样,但是解决方法是通过手动调用如下方法直接从UI线程中调用我们想要的代码

System.Timers.Timer ConnectionCheckerTimer;


private void InitializeConnectionCheckerTimer()
{
    ConnectionCheckerTimer = new System.Timers.Timer(5000);
    ConnectionCheckerTimer.Elapsed += OnTimedEvent;
    ConnectionCheckerTimer.AutoReset = true;
    ConnectionCheckerTimer.Enabled = true;
}

1 个答案:

答案 0 :(得分:-1)

我能够通过手动调用UI线程的Dispatcher并从那里执行代码来使其工作。

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    if (DataServices.Instance.State == DataServicesState.Up && _timeSeries.ServiceInformation.State == ServiceState.Up)
    {

    }
    else
    {
        Application.Current.Dispatcher.Invoke(
            () =>
            {
                OpenConnections();
            });
    }
}