使用定时器刷新界面,持续获取"There is already an open DataReader associated with this Connection which must be closed first."

Using timer to refresh interface, keep getting "There is already an open DataReader associated with this Connection which must be closed first."

我一直在使用计时器刷新我的应用程序上的列表视图,但半秒后,我首先收到错误消息 try/catch method in RefreshPlot() in PlotComponent.cs:

An exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in Marketplace.exe but was not handled in user code

Additional information: There is already an open DataReader associated with this Connection which must be closed first.

这是怎么回事?我试过使用 usingtry/catch,所以我不太清楚我可能犯的错误。当我禁用计时器时,一切正常。但是我需要每 0.5 秒访问一次数据库以刷新列表视图。

如果我没有按照正确的方式去做,我还能做些什么吗?

代码如下:

MainWindow.cs

public MainWindow()
{
    InitializeComponent();

    // Reset lists
    SetPlotList(_filterPlotReference);

    // Refresh lists
    Refresh();
}

public void Refresh()
{
    var myTimer = new System.Timers.Timer();
    myTimer.Elapsed += RefreshPlotList;
    myTimer.Interval = 500;
    myTimer.Enabled = true;
}

public void RefreshPlotList(object source, ElapsedEventArgs e)
{
    PlotComponent.RefreshPlot();
    Dispatcher.Invoke(() =>
    {
        if (!string.IsNullOrWhiteSpace(FilterTextBox.Text) &&
            (!Regex.IsMatch(FilterTextBox.Text, "[^0-9]")))
        {
            _filterPlotReference = Convert.ToInt32(FilterTextBox.Text);
        }
    });
    SetPlotList(_filterPlotReference);
    FocusPlotItem(_focusPlotReference);
}

public void SetPlotList(int filterReference)
{
    // Fill plot list view
    List<PlotComponent.PlotList> plotList = PlotComponent.SelectPlotLists(filterReference);

    // Find the plot list item in the new list
    PlotComponent.PlotList selectPlotList =
        plotList.Find(x => Convert.ToInt32(x.PlotId) == _focusPlotReference);

    Dispatcher.Invoke(
        (() =>
        {
            PlotListView.ItemsSource = plotList;
            if (selectPlotList != null)
            {
                PlotListView.SelectedItem = selectPlotList;
            }
        }));

    int jobSum = 0;
    int bidSum = 0;
    foreach (PlotComponent.PlotList item in PlotListView.Items)
    {
        jobSum += Convert.ToInt32(item.Jobs);
        bidSum += Convert.ToInt32(item.Bids);
    }

    // Determine job/bid list ratio
    Dispatcher.BeginInvoke(
        new ThreadStart(() => JobBidRatioTextBlock.Text = jobSum + " jobs - " + bidSum + " bids"));
}

private void FocusPlotItem(int focusPlotReference)
{
    Dispatcher.Invoke(
        (() =>
        {
            PlotComponent.PlotList plotList =
                PlotListView.Items.OfType<PlotComponent.PlotList>()
                    .FirstOrDefault(p => Convert.ToInt32(p.PlotId) == focusPlotReference);
            if (plotList == null) return;
            //get visual container
            var container = PlotListView.ItemContainerGenerator.ContainerFromItem(plotList) as ListViewItem;
            if (container == null) return;
            container.IsSelected = true;
            container.Focus();
        }));
}

DbConnect.cs

http://pastebin.com/pZ0PGrg1

PlotComponent.cs

http://pastebin.com/xiRhKyMM

非常感谢您的提前帮助。

能否在 RefreshPlotList 函数完成之前禁用计时器?

可以在函数开始时禁用定时器,并在 RefreshPlotList 函数结束时启用定时器。我猜 RefreshPlotList 函数花费的时间超过 0.5 秒,并且在当前调用完成之前进行了另一个调用。

这是一个锁定定时器直到它完成工作的例子:

bool timerRunning = false; // define it as a global variable

// then in your timer process add this easy check
public void RefreshPlotList(object source, ElapsedEventArgs e)
{
    if(timerRunning) return; // return if it is busy
    timerRunning = true;  // set it to busy

    PlotComponent.RefreshPlot();
    Dispatcher.Invoke(() =>
    {
        if (!string.IsNullOrWhiteSpace(FilterTextBox.Text) &&
            (!Regex.IsMatch(FilterTextBox.Text, "[^0-9]")))
        {
            _filterPlotReference = Convert.ToInt32(FilterTextBox.Text);
        }
    });
    SetPlotList(_filterPlotReference);
    FocusPlotItem(_focusPlotReference);

    timerRunning = false;  // reset it for next time use
}

P.S:我通过添加(完全)这个答案来编辑另一个答案,然后我被拒绝了,同行评审说

This edit was intended to address the author of the post and makes no sense as an edit. It should have been written as a comment or an answer

我毫不怀疑他们确实阅读了编辑并对其进行了评估,更不用说它不适合发表评论了,所以我在这里 post 作为答案