バックグラウンドでデータをダウンロードする wpf xbap アプリケーションがあります。アプリケーションの終了時に、ダウンロードを停止してキャッシュをフラッシュする必要があります。現在は次のように実装されています:
App.xaml:
<Application Exit="ApplicationExit">
App.xaml.cs :
private void ApplicationExit(object sender, ExitEventArgs e)
{
BackgroundImageLoader.Instance.Stop(); // target
ViewModelLocator.Cleanup();
FileCacheHelpers.FlushTemporaryFolder();
}
BackgroundImageLoader.cs :
// Thread-safe singleton
public sealed class BackgroundImageLoader
{
private static volatile BackgroundImageLoader _instance;
private static readonly object SyncRoot = new object();
private BackgroundImageLoader() { }
public static BackgroundImageLoader Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
_instance = new BackgroundImageLoader();
}
}
return _instance;
}
}
// other properties, omitted for conciseness
private Task loaderTask;
private CancellationTokenSource ts;
public void Start()
{
ts = new CancellationTokenSource();
var ct = ts.Token;
loaderTask = Task.Factory.StartNew(() =>
{
// TaskList is an array of tasks that cannot be canceled
// if they were executed, so i want to actually cancel the
// whole pool after last non-canceled operation was ended
foreach (var task in TasksList)
{
if (ct.IsCancellationRequested)
{
Debug.WriteLine("[BackgroundImageLoader] Cancel requested");
// wait for last operation to finish
Thread.Sleep(3000);
FileCacheHelpers.FlushTemporaryFolder();
break;
}
task.DoSomeHeavyWorkHere();
}
}, ct);
}
public void Stop()
{
if (loaderTask != null)
{
if (loaderTask.Status == TaskStatus.Running)
{
ts.Cancel();
}
}
}
}
Stop が呼び出され、loaderTask は null ではなく、Status は Running ですが、ts.Cancel() の後 IsCancellationRequested プロパティは変更されません (ここで説明されているように、タスク全体を while(true){..} 内にラップした後でも)。読み込みが停止しますが、自動 GC のおかげでのみ発生すると思います。私のフラッシュメソッドは実行されません。私は何が欠けていますか?psまた、別のスレッドで同時にタスクを実行するように機能をリファクタリングする必要がありますが、副作用を恐れています。どんな助けでも感謝します。前もって感謝します。