0

我正在使用文件观察器监视文件输出,然后使用 d3(动态数据显示)动态显示结果。这里有更多细节:

  1. 数据是一系列快速生成的 tiff 文件(每个文件生成 20-25 毫秒);
  2. 一旦有文件进来,就会触发事件,并处理文件(一些统计计算);
  3. 结果将被发送到 d3 绘图仪,该绘图仪将在宪章上动态显示结果。

当我关闭 d3 包机窗口时,文件观察程序捕获几乎所有事件,但这是我的问题:

  • 但是,当我打开 d3 宪章窗口时,即使没有任何统计数据计算,文件观察程序也会丢弃许多事件(发生一些大差距)。

这是我们尝试过的:

  • 增加观察者缓冲区,但是,只要 d3 宪章窗口打开,它仍然会丢弃事件。
  • 使用 C++ dll 计算统计数据,但它看起来更慢。

所以我想知道:

  • d3 绘图仪和文件观察器是否相互冲突/干扰?
  • 我可以将它们一起用于实时绘图吗?
  • 有没有办法解决我的问题?

任何指针表示赞赏。

这是d3绘图仪的代码,包括构造函数、绘图仪启动器和绘图仪更新:

#region Constructor
public SignalStatsDisplay()
{
    InitializeComponent();

    //   timeDomainPlotter.Legend.Remove();

    _initialChildrenCount = timeDomainPlotter.Children.Count;

    int count = timeDomainPlotter.Children.Count;

    //do not remove the initial children
    if (count > _initialChildrenCount)
    {
        for (int i = count - 1; i >= _initialChildrenCount; i--)
        {
            timeDomainPlotter.Children.RemoveAt(i);
        }
    }

    _nMaxStatsOneChannel = Enum.GetNames(typeof(Window1.ROISignalList)).Length;
    _curveBrush = new Brush[_nMaxStatsOneChannel];
    _statsEnable = new int[_nMaxStatsOneChannel];

    for (int i = 0; i < _nMaxStatsOneChannel; i++)
    {
        _curveBrush[i] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(_colorList[i]));
        _statsEnable[i] = 0;
    }

    _nActiveStatsOneChannel = 0;
}
#endregion Constructor

public void InitiateSignalAnalysisPlot()
{
    _statsName = Enum.GetNames(typeof(Window1.ROISignalList));

    int count = 0;
    _statsEnableIndex = new int[_nActiveStatsOneChannel];
    for (int i = 0; i < _nMaxStatsOneChannel; i++)  // assign color
    {
        if (_statsEnable[i] == 1)
        {
            _statsEnableIndex[count] = i;
            count++;
        }
    }



    if (_nActiveChannel > 0)    // timeDomainPlotter init
    {
        _dataX = new List<double[]>();
        _dataY = new List<double[]>();

        double[] dataXOneCh = new double[_signalLength];
        double[] dataYOneCh = new double[_signalLength];

        dataXOneCh[0] = 0;
        dataYOneCh[0] = 0;

        for (int i = 0; i < _nActiveChannel; i++)
        {
            for (int j = 0; j < _nActiveStatsOneChannel; j++)
            {
                _dataX.Add(dataXOneCh);    // data x-y mapping init
                _dataY.Add(dataYOneCh);

                EnumerableDataSource<double> xOneCh = new EnumerableDataSource<double>(dataXOneCh);
                EnumerableDataSource<double> yOneCh = new EnumerableDataSource<double>(dataYOneCh);

                xOneCh.SetXMapping(xVal => xVal);
                yOneCh.SetXMapping(yVal => yVal);

                CompositeDataSource dsOneCh = new CompositeDataSource(xOneCh, yOneCh);

                LineAndMarker<MarkerPointsGraph> lam = timeDomainPlotter.AddLineGraph(dsOneCh,
                    new Pen(_curveBrush[_statsEnableIndex[j]], 2),
                    new CirclePointMarker { Size = 5, Fill = _curveBrush[_statsEnableIndex[j]] },
                    new PenDescription(_statsName[_statsEnableIndex[j]]));

            }
        }

        Action FitToView = delegate()
        {
            timeDomainPlotter.FitToView();
        };
        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, FitToView);
    }
    else
    {
        return;
    }
}

public void RedrawSignalAnalysisPlot()
{
    int startIndex = _initialChildrenCount;

    if ((_nActiveStatsOneChannel > 0) && (_dataX != null) && (_dataY != null))
    {
        CompositeDataSource[] dsCh = new CompositeDataSource[_nActiveStatsOneChannel];
        int m, n;
        int index;

        for (int i = 0; i < _nActiveChannel; i++)
        {
            for (int j = 0; j < _nActiveStatsOneChannel; j++)
            {
                index = i * _nActiveStatsOneChannel + j;
                if (_dataX[index].Length == _dataY[index].Length)
                {
                    EnumerableDataSource<double> xOneCh = new EnumerableDataSource<double>(_dataX[index]);
                    xOneCh.SetXMapping(xVal => xVal);
                    EnumerableDataSource<double> yOneCh = new EnumerableDataSource<double>(_dataY[index]);
                    yOneCh.SetYMapping(yVal => yVal);
                    CompositeDataSource ds = new CompositeDataSource(xOneCh, yOneCh);

                    Action UpdateData = delegate()
                    {
                        m = i * 2;
                        n = j * 2;

                        // ((LineGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + m * _nActiveStatsOneChannel)).DataSource = ds;
                        // ((LineGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + m * _nActiveStatsOneChannel)).LinePen
                        //    = new Pen(new SolidColorBrush(_curveBrush[j]), 1);

                        ((MarkerPointsGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + 1 + m * _nActiveStatsOneChannel)).DataSource = ds;
                        //  ((MarkerPointsGraph)timeDomainPlotter.Children.ElementAt(startIndex + n + 1 + m * _nActiveStatsOneChannel)).Marker
                        //      = new CirclePointMarker { Size = 5, Fill = Brushes.Green };
                    };

                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, UpdateData);
                }

            }


        }

        /* Action PlotFitToView = delegate()
          {
              timeDomainPlotter.FitToView();
          };

         this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, PlotFitToView);*/
    }
}

以下是文件的监控方式: 事件(文件写入)的归档位置

void tiffWatcher_EventChanged(object sender, WatcherExEventArgs e)
{
    string fileName = ((FileSystemEventArgs)(e.Arguments)).FullPath;
    string fileExt = StringExtension.GetLast(fileName, 4);

    if (!IsFileLocked(fileName))
    {

        Action EventFinished = delegate()
        {
            CreateListViewItem(fileName, "Finished", DateTime.Now.ToString("HH:mm:ss.fff"));
        };

        listView1.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, EventFinished);

        _tiffName.Add( fileName);
        _tiffFilledCount++;    
    }
}

tiff 数据处理,以及与 d3 绘图仪的数据通信:

void tiffTimer_Tick(object sender, EventArgs e)
{
    //throw new NotImplementedException();
    byte[] image = new byte[_signalManager.ImgWidth * _signalManager.ImgHeight];

    if (_tiffFilledCount - _tiffProcessedCount >= 1)
    {


        string fileName = _tiffName[_tiffProcessedCount++];
        char filePre = fileName[49];
        int indexBeigin = fileName.LastIndexOf("_");
        int indexEnd = fileName.LastIndexOf(".");

        _signalIndex = Convert.ToInt32(fileName.Substring(indexBeigin + 1, indexEnd - indexBeigin - 1)) - 1; // 0 based//
        _deltaT = ExtractTiffDeltaT(fileName, "DeltaT=", 1);
        _channelIndex = (int)Enum.Parse(typeof(ChannelList), Convert.ToString(filePre));
        TIFFIImageIO.LoadTIFF(fileName, ref image);
        _signalManager.Image = image;
        for (int i = 0; i < _nActiveStatsOneChannel; i++)
        {
            _signalManager.GetSignal( _signalDisplay.StatsEnableIndex[i], ref _signal);
            UpdateSignal(_channelIndex, i, _tiffProcessedCount-1, _deltaT, _signal);
        }

      // if( _tiffProcessedCount % 5 == 0)
        _signalDisplay.SetData(_XList, _YList, true);
    }
}

我使用 Timer.Tick 每 50-100 毫秒处理一次文件,仍在测试。

4

1 回答 1

0

我处理它的方式是设置一个定时器,循环处理计算,显示。到目前为止,它工作正常。当然会有很多事件丢失,但是我们处理大量的点(数千个),所以数百个做情节是可以的。这是代码:

private Timer _tiffTimer;
void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
            _tiffTimer = new Timer();
            _tiffTimer.Interval = 50;  // change interval to change performance
            _tiffTimer.Tick += new EventHandler(tiffTimer_Tick);
            _tiffTimer.Start();

        }

void tiffTimer_Tick(object sender, EventArgs e)
        {
            //do your stuff here

        }
于 2013-03-07T15:43:45.740 回答