C# 在WPF XBAP应用程序退出期间取消后台任务

C# 在WPF XBAP应用程序退出期间取消后台任务,c#,wpf,task,xbap,cancellation,C#,Wpf,Task,Xbap,Cancellation,我有一个WPFXBAP应用程序,可以在后台下载一些数据。需要停止下载并在应用程序退出时刷新缓存。现在实现如下: App.xaml: <Application Exit="ApplicationExit"> BackgroundImageLoader.cs: // Thread-safe singleton public sealed class BackgroundImageLoader { private static volatile BackgroundIma

我有一个WPFXBAP应用程序,可以在后台下载一些数据。需要停止下载并在应用程序退出时刷新缓存。现在实现如下:
App.xaml:

<Application Exit="ApplicationExit">
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且状态为正在运行,但在ts.Cancel()之后,不会更改IsCancellationRequested属性(即使在将整个任务包装到while(true){..}中之后,如所述)。加载停止了,但我想这只能归功于自动GC。我的flush方法没有执行。我错过了什么?
p、 我还需要重构功能,以便在不同的线程中同时运行任务,但担心会产生副作用。谢谢你的帮助。提前感谢。

添加了一些手动标志,我在处理过程中设置和检查这些标志,并在Start()开始时调用Stop(),因此行为是可以接受的

// 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();        
                }
            }
        }
    }