【发布时间】:2013-11-15 14:06:55
【问题描述】:
当列表框的部分项目更改时,我有以下任务运行。
当用户更改选择并开始新任务时,我正在尝试取消正在运行的任何任务。我似乎可以弄清楚为什么代码不起作用。
代码
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 (用户在加载之前不会更改选择)。
【问题讨论】:
-
您能否更具体地了解“不工作”?
-
对不起,任务没有取消
-
您需要在 LoadSeriesAsync 中手动检查
token.IsCancellationRequested- 请参阅stackoverflow.com/a/3713113/43846 -
Thread.Sleep(9000) 不是对异步代码的正确模拟。它会冻结你的用户界面。并且不要在运行昂贵的代码之前检查取消,在运行它时检查它。
-
@Hans Passant 嗨,我应该在代码中的哪个位置检查是否正在调用取消令牌?你介意编辑我的例子来告诉我你的意思吗?