0

我有一个应用程序,当用户为列表框选择一个项目时,它会执行一项耗时的任务。

当用户选择一个节目时,应用程序将从 tvdb 中检索所有节目信息并将其显示在 Ui 中。

当用户在节目仍在加载时快速更改选择时,就会出现此问题。

我想这样做,以便用户可以改变主意,然后在第一个加载时进行另一个选择,并将该信息显示在 Ui 中。

我创建了一个简单的演示应用程序来显示问题:Demo App

这就是我试图做的

列表框选择事件处理程序

private  void lb1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string sid = lb1.SelectedItem.ToString();

            try
            {
                LoadSeries(Int32.Parse(sid));
            }
            catch (FormatException)
            {
                MessageBox.Show("Please enter a valid series id");
            }
        }

负载系列

private void LoadSeries(int _seriesId)
{

    Task<TvdbSeries> series = Task.Factory.StartNew(() =>
    {
        TvdbSeries seriesloaded = null;
        try
        {
            seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);
        }
        catch (TvdbInvalidApiKeyException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (TvdbNotAvailableException ex)
        {
            MessageBox.Show(ex.Message);
        }

        return seriesloaded;
    }
     );

    series.ContinueWith((antecedent) =>
    {
        UpdateSeries(series.Result);
    },
        TaskScheduler.FromCurrentSynchronizationContext()
    );

}

如果用户快速更改选择,则应用程序错误在线seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);并在调试器中显示此消息“ WebClient 不支持并发 I/O 操作。

我确实发现这是因为我在最后一个请求完成之前发出了一个新请求,但我无法将代码链接到 m_tvdbHandler.GetSeries 中,因为它的功能来自我正在使用的库和其他人编写的库。

这是tvdblib库,我确信问题在于我如何做事,而不是库。

4

2 回答 2

1

当用户进行选择时,您可以禁用 UI,直到信息完全加载并在底部加载时显示一条消息,请稍候。加载完所有内容后,启用 Ui 并隐藏消息。

于 2013-10-20T14:15:15.983 回答
0

您将此问题发布为C#5.0问题,因此您应该尽可能多地使用async/ 。await

private Task<TvdbSeries> LoadSeriesAsync(int _seriesId)
{

    return Task.Run(() =>
    {
        TvdbSeries seriesloaded = null;
        try
        {
            seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);
        }
        catch (TvdbInvalidApiKeyException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (TvdbNotAvailableException ex)
        {
            MessageBox.Show(ex.Message);
        }

        return seriesloaded;
    }
     );
}

如果有一个就更好了LoadSeriesAsync

一种方法是在检索系列时禁用lb1 。

私人异步无效lb1_SelectionChanged(对象发送者,SelectionChangedEventArgs e){字符串sid = lb1.SelectedItem.ToString();

try
{
    lb1.IsEnabled = false;
    var series = await LoadSeriesAsync(Int32.Parse(sid));

    UpdateSeries(series);
}
catch (FormatException)
{
    MessageBox.Show("Please enter a valid series id");
    lb1.IsEnabled = true;
}

}

于 2013-10-21T07:49:44.810 回答