创建新任务时取消所有任务

时间:2013-10-23 15:29:27

标签: c# .net-4.5 c#-5.0

当列表框的节项发生更改时,我执行以下任务。

我正在尝试取消用户更改其选择并开始新任务时正在运行的任何任务。我似乎可以弄清楚代码无法正常工作的原因。

代码

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 运行 LoadSeriesAsync (用户在加载之前不会更改选择。)

2 个答案:

答案 0 :(得分: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) { }通常是个坏主意;通常,所需的语义是允许取消传播出去。

答案 1 :(得分:-1)

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