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 をチェックします。簡単

于 2013-11-15T06:06:55.110 に答える