2013-10-23 1 views
5

목록 상자의 섹션 항목이 변경 될 때 실행되는 다음 작업이 있습니다.새 작업이 생성 될 때 모든 작업 취소

사용자가 선택을 변경하고 새 작업을 시작할 때 실행중인 작업을 취소하려고합니다. 코드가 작동하지 않는 이유를 알아낼 수 있습니다.

LoadSeriesAsync을 완료 할 수있는 경우 내가 LoadPosterAsync를 실행하는 다른 모든 이벤트를 취소 에게 LoadSeriesAsync를 얻으려고 노력하고 만 을 실행하고

그래서
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; 
     } 

코드 (사용자는로드되기 전에 선택 사항을 변경하지 않습니다.)

+0

"작동하지 않는다"에 대해 더 구체적으로 설명 할 수 있습니까? – stuartd

+0

죄송합니다, 작업이 취소되지 않습니다 – justinf

+0

LoadSeriesAsync에서'token.IsCancellationRequested'를 수동으로 확인해야합니다 - http://stackoverflow.com/a/3713113/43846 – stuartd

답변

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) { }을 수행하는 것은 좋지 않습니다. 대개 원하는 의미는 취소가 전파되도록 허용하는 것입니다.

+0

나는 당신의 제안을 시도했지만 작업이 취소 된 것 같지 않습니다. 나는'seriesloaded = m_tvdbHandler.GetSeries' 전에 잠을 자서 내가 선택을 바꿨을 때 선택을 빠르게 바꿀 때 작업을 느리게 할 것이므로 하나 이상의 작업이 있고 취소되지는 않았 음을 알 수있다. 이것은 [작업 화면] (http://i.imgur.com/mRHpX42.jpg?1)처럼 보입니다. – justinf

+0

필자가 대답했듯이 취소 토큰을 사용하도록'GetSeries'를 수정해야합니다. –

+0

다른 방법으로는 GetType을 변경할 수 없기 때문에 GetSeries를 사용할 수 있습니다. 왜냐하면 그 기능은 다른 사람이 만든 사용자 정의 dll에서 비롯된 것이므로 코드를 제어 할 수 없기 때문입니다. – justinf

-1

사용 스레드 및 선택 Thread.IsAlive가 true 인 경우 Thread.Abort()와 Thread.Start(); 쉬운

관련 문제