5

当列表框的部分项目更改时,我有以下任务运行。

当用户更改选择并开始新任务时,我正在尝试取消正在运行的任何任务。我似乎可以弄清楚为什么代码不起作用。

编码

CancellationTokenSource cts;
// The event handeler for when the user makes a selection in the list box 
private async void lb1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    clearfileds();

    if (cts != null)
       { cts.Cancel(); }

    cts = new CancellationTokenSource();

    var token = cts.Token;
    string sid = lb1.SelectedItem.ToString();

    try
    {   
        var series = await LoadSeriesAsync(token, Int32.Parse(sid));
        var poster = await LoadPosterAsync(series.PosterBanners[0]);

        UpdateSeries(series);
        if (File.Exists(poster))
        {
            ImageSource imageSource = new BitmapImage(new Uri(poster));
            imgPoster.Source = imageSource;
        }
    }
    catch (OperationCanceledException)
    {MessageBox.Show("we cancell some thing");}

    catch (FormatException)
    {MessageBox.Show("Please enter a valid series id");}

}


private async Task<TvdbSeries> LoadSeriesAsync(CancellationToken ct, int _seriesId)
    {  TvdbSeries seriesloaded = null;
       CancellationToken token = ct;

        Task<TvdbSeries> SeriesLoadTask = Task.Run(() =>
        {   
            m_tvdbHandler = new TvdbHandler(CacheProvider, "49E28C3EB13EB1CF");
            m_tvdbHandler.InitCache();
            token.ThrowIfCancellationRequested();

            try
            {   seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);
                //Just for the test 
                System.Threading.Thread.Sleep(9000);
            }

            catch (OperationCanceledException)
            { }

            catch (TvdbInvalidApiKeyException ex)
            { MessageBox.Show(ex.Message);}
            catch (TvdbNotAvailableException ex)
            { MessageBox.Show(ex.Message);}

            return seriesloaded;
        });

        try
        { seriesloaded = await SeriesLoadTask; }

        catch (OperationCanceledException)
                {}
        return seriesloaded;
    }


 private  async Task<string> LoadPosterAsync(object _param)
        {
            string posterpath ;
            Task<string> PosterLoad = Task.Run(() =>
            {

                TvdbPosterBanner banner = (TvdbPosterBanner)_param;
                banner.LoadBanner();
                posterpath = CacheFolder + @"\" + banner.SeriesId + @"\img_posters_" + (banner.BannerPath).Replace(@"posters/", "");
                return posterpath;
            });


            try
            { posterpath = await PosterLoad; }

            catch (OperationCanceledException)
                {   
                    posterpath = "";
                }
            return posterpath;
        }

因此,我试图让LoadSeriesAsync取消所有其他正在运行的事件,然后仅在允许LoadSeriesAsync完成时才运行LoadPosterAsync(用户在加载之前不会更改选择)。

4

2 回答 2

3

我试图让 LoadSeriesAsync 取消所有其他正在运行的事件,然后仅在允许 LoadSeriesAsync 完成时才运行 LoadPosterAsync

因此,只需在调用之前检查令牌LoadPosterAsync

var series = await LoadSeriesAsync(token, Int32.Parse(sid));
token.ThrowIfCancellationRequested();
var poster = await LoadPosterAsync(series.PosterBanners[0]);

附带说明一下,您应该将token堆栈传递给任何长时间运行的操作,例如TvdbHandler.GetSeries.

此外,这样做通常是个坏主意catch (OperationCanceledException) { };通常,所需的语义是允许取消传播。

于 2013-10-23T17:49:08.237 回答
-1

使用 Thread 并在选择时检查 Thread.IsAlive 是否等于 true Thread.Abort() 然后 Thread.Start(); 简单的

于 2013-11-15T06:06:55.110 回答