博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows phone 8 学习笔记(6) 多任务
阅读量:4315 次
发布时间:2019-06-06

本文共 32100 字,大约阅读时间需要 107 分钟。

Windows phone 8 是一个单任务操作系统,任何时候都只有一个应用处于活跃状态,这里的多任务是指对后台任务的支持。本节我们先讲讲应用程序的运行状态,然后看看支持的后台任务,包括:后台代理、后台音频、后台文件传输、后台辅助线程等。

快速导航:

   
   
   
   
   

一、应用的状态

1)应用的运行状态

我们通过图解来分析应用的运行状态,启动并置于前台界面的应用是唯一处于运行状态的,其他的操作,比如win键,后退导出应用,打开选择器和启动器时都会让当前运行的应用进入休眠状态,如果系统内存不足,处于休眠状态的应用可能会被系统逻辑删除。下面的图示演示了这个过程。

2)如何恢复状态

当应用处于休眠状态时,它的状态信息仍然保留在内存中,用户下次切换进去后不会有任何变化。但是当应用被逻辑删除后,这些状态信息就会丢失,比如表单填写的内容都会消失,为了避免这种情况,我们需要手动保留状态信息。

    首先,我们在mainpage定义一些页面表单控件:

[XAML]

我们需要实现在应用逻辑删除后能将其状态保持到页面的State字典中,但是需要我们的数据源支持序列化,所以我们定义与表单关联的ViewModel如下:

[C#]
[DataContract]    public class ViewModel : INotifyPropertyChanged    {        private string _textBox1Text;        private bool _checkBox1IsChecked;        private bool _radioButton1IsChecked;        private bool _radioButton2IsChecked;        private double _slider1Value;        [DataMember]        public string TextBox1Text        {            get { return _textBox1Text; }            set            {                _textBox1Text = value;                NotifyPropertyChanged("TextBox1Text");            }        }        [DataMember]        public bool CheckBox1IsChecked        {            get { return _checkBox1IsChecked; }            set            {                _checkBox1IsChecked = value;                NotifyPropertyChanged("CheckBox1IsChecked");            }        }        [DataMember]        public double Slider1Value        {            get { return _slider1Value; }            set            {                _slider1Value = value;                NotifyPropertyChanged("Slider1Value");            }        }        [DataMember]        public bool RadioButton1IsChecked        {            get { return _radioButton1IsChecked; }            set            {                _radioButton1IsChecked = value;                NotifyPropertyChanged("RadioButton1IsChecked");            }        }        [DataMember]        public bool RadioButton2IsChecked        {            get { return _radioButton2IsChecked; }            set            {                _radioButton2IsChecked = value;                NotifyPropertyChanged("RadioButton2IsChecked");            }        }        public event PropertyChangedEventHandler PropertyChanged;        private void NotifyPropertyChanged(string propertyName)        {            if (null != PropertyChanged)                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));        }    }

我需要对mainpage代码添加页面导航入、导航出的事件。导航出页面的时候,如果不是向后导航,则存储状态。导航入的时候,我们需要判断页面是否为逻辑删除后正在恢复的状态,如果是,则通过状态字典恢复状态。mainpage代码如下:

[C#]
public partial class MainPage : PhoneApplicationPage    {        // 构造函数        public MainPage()        {            InitializeComponent();            _isNewPageInstance = true;        }        ViewModel _viewModel = null;        ///         /// 新实例还是现有实例        ///         bool _isNewPageInstance = false;        private void Button_Click_1(object sender, RoutedEventArgs e)        {            NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));        }        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)        {            //如果不是向后导航,则保存状态            if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)            {                State["ViewModel"] = _viewModel;            }        }        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)        {            if (_isNewPageInstance)            {                if (_viewModel == null)                {                    if (State.Count > 0)                    {                        _viewModel = (ViewModel)State["ViewModel"];                    }                    else                    {                        _viewModel = new ViewModel();                    }                }                DataContext = _viewModel;            }            _isNewPageInstance = false;        }    }

然后我们添加一page1页面,该页添加一个返回按钮。用于测试。为了达到调试时即时进入逻辑删除的效果,我们需要设置下。右键项目文件,点属性,在调试选项卡勾选“在调试期间取消激活时逻辑删除”。

 

二、后台代理

后台代理可以在应用退出以后独立在系统后台运行,它包含两种类型的代理,分别是定期代理和资源密集型代理,前者用于频繁执行小任务,后者用于在系统空闲时执行耗时大任务。要使用后台代理,我们需要添加一个名为Windows phone 计划任务代理的项目,并在应用的项目中添加对其的引用,现在我们要实现在后台代理中弹出Toast,我们需要如下修改ScheduledAgent.cs的OnInvoke方法,代码如下

[C#]
protected override void OnInvoke(ScheduledTask task)        {            string toastMessage = "";            if (task is PeriodicTask)            {                toastMessage = "定期代理正在运行";            }            else            {                toastMessage = "资源密集型代理正在运行";            }            // 用于向用户显示Toast,如果当前任务的前台正在运行,则不显示            ShellToast toast = new ShellToast();            toast.Title = "标题";            toast.Content = toastMessage;            toast.Show();            // 在调试的时候需要及时执行查看效果            #if DEBUG_AGENT                ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(15));            #endif            NotifyComplete();        }

接着,我们在应用项目的mainpage中调用代理,代码如下:

[XAML]
[C#]
public partial class MainPage : PhoneApplicationPage    {        ///         /// 定期代理        ///         PeriodicTask periodicTask;        ///         /// 资源密集型代理        ///         ResourceIntensiveTask resourceIntensiveTask;        string periodicTaskName = "PeriodicAgent";        string resourceIntensiveTaskName = "ResourceIntensiveAgent";        public bool agentsAreEnabled = true;        // 构造函数        public MainPage()        {            InitializeComponent();        }        //启动定期代理        private void StartPeriodicAgent()        {            agentsAreEnabled = true;            // 获取当前名称的定期代理,如果存在则移除            periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;            if (periodicTask != null)            {                RemoveAgent(periodicTaskName);            }            periodicTask = new PeriodicTask(periodicTaskName);            periodicTask.Description = "这是一个定期代理的描述信息。";            try            {                ScheduledActionService.Add(periodicTask);                PeriodicStackPanel.DataContext = periodicTask;                //在调试的时候需要及时执行查看效果                #if(DEBUG_AGENT)                    ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));                #endif            }            catch (InvalidOperationException exception)            {                if (exception.Message.Contains("BNS Error: The action is disabled"))                {                    MessageBox.Show("本应用的后台计划被用户禁用。");                    agentsAreEnabled = false;                    PeriodicCheckBox.IsChecked = false;                }                if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))                {                    MessageBox.Show("定期代理数量达到最大限制。");                }                PeriodicCheckBox.IsChecked = false;            }            catch (SchedulerServiceException)            {                PeriodicCheckBox.IsChecked = false;            }        }        private void StartResourceIntensiveAgent()        {            agentsAreEnabled = true;            // 获取当前名称的资源密集型代理,如果存在则移除            resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;            if (resourceIntensiveTask != null)            {                RemoveAgent(resourceIntensiveTaskName);            }            resourceIntensiveTask = new ResourceIntensiveTask(resourceIntensiveTaskName);            resourceIntensiveTask.Description = "这是一个资源密集型代理的描述信息。";            try            {                ScheduledActionService.Add(resourceIntensiveTask);                ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;                //在调试的时候需要及时执行查看效果                #if(DEBUG_AGENT)                    ScheduledActionService.LaunchForTest(resourceIntensiveTaskName, TimeSpan.FromSeconds(15));                #endif            }            catch (InvalidOperationException exception)            {                if (exception.Message.Contains("BNS Error: The action is disabled"))                {                    MessageBox.Show("本应用的后台计划被用户禁用。");                    agentsAreEnabled = false;                }                ResourceIntensiveCheckBox.IsChecked = false;            }            catch (SchedulerServiceException)            {                ResourceIntensiveCheckBox.IsChecked = false;            }        }        bool ignoreCheckBoxEvents = false;        private void PeriodicCheckBox_Checked(object sender, RoutedEventArgs e)        {            if (ignoreCheckBoxEvents)                return;            StartPeriodicAgent();        }        private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e)        {            if (ignoreCheckBoxEvents)                return;            RemoveAgent(periodicTaskName);        }        private void ResourceIntensiveCheckBox_Checked(object sender, RoutedEventArgs e)        {            if (ignoreCheckBoxEvents)                return;            StartResourceIntensiveAgent();        }        private void ResourceIntensiveCheckBox_Unchecked(object sender, RoutedEventArgs e)        {            if (ignoreCheckBoxEvents)                return;            RemoveAgent(resourceIntensiveTaskName);        }        ///         /// 删除代理        ///         private void RemoveAgent(string name)        {            try            {                ScheduledActionService.Remove(name);            }            catch (Exception)            {            }        }        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)        {            ignoreCheckBoxEvents = true;            periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;            if (periodicTask != null)            {                PeriodicStackPanel.DataContext = periodicTask;            }            resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;            if (resourceIntensiveTask != null)            {                ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;            }            ignoreCheckBoxEvents = false;        }    }

 

三、后台音频

通过后台音频的功能我们可以实现在系统后台播放音乐的功能,由于后台音频代理只能访问本地文件夹,所以我们务必要先把需要播放的音乐文件拷贝到本地文件夹中。本示例是把安装文件夹的音频文件拷贝到本地文件夹,代码如下:

[C#]
//把安装文件夹下的文件拷贝到本地文件夹        private void CopyToIsolatedStorage()        {            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())            {                string[] files = new string[] { "Ring01.wma", "Ring02.wma", "Ring03.wma" };                foreach (var _fileName in files)                {                    if (!storage.FileExists(_fileName))                    {                        string _filePath = "Audio/" + _fileName;                        StreamResourceInfo resource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative));                        using (IsolatedStorageFileStream file = storage.CreateFile(_fileName))                        {                            int chunkSize = 4096;                            byte[] bytes = new byte[chunkSize];                            int byteCount;                            while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)                            {                                file.Write(bytes, 0, byteCount);                            }                        }                    }                }                string[] icons = new string[] { "Ring01.jpg", "Ring02.jpg", "Ring03.jpg" };                foreach (var _fileName in icons)                {                    if (!storage.FileExists(_fileName))                    {                        string _filePath = "Images/" + _fileName;                        StreamResourceInfo iconResource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative));                        using (IsolatedStorageFileStream file = storage.CreateFile( _fileName))                        {                            int chunkSize = 4096;                            byte[] bytes = new byte[chunkSize];                            int byteCount;                            while ((byteCount = iconResource.Stream.Read(bytes, 0, chunkSize)) > 0)                            {                                file.Write(bytes, 0, byteCount);                            }                        }                    }                }            }        }

我们需要在解决方案中添加Windows phone 音频播放代理项目,并在应用项目中添加对其的引用。修改AudioPlayer.cs代码如下:

[C#]
public class AudioPlayer : AudioPlayerAgent    {        private static volatile bool _classInitialized;        private static List
_playList = new List
{ new AudioTrack(new Uri("Ring01.wma", UriKind.Relative),"曲目1","艺术家1","专辑1",new Uri("Ring01.jpg", UriKind.Relative)), new AudioTrack(new Uri("Ring02.wma", UriKind.Relative),"曲目2","艺术家2","专辑2",new Uri("Ring02.jpg", UriKind.Relative)), new AudioTrack(new Uri("Ring03.wma", UriKind.Relative),"曲目3","艺术家3","专辑3",new Uri("Ring03.jpg", UriKind.Relative)) }; ///
/// 当前播放位置 /// static int currentTrackNumber = 0; ///
/// AudioPlayer 实例可共享同一进程。 /// 静态字段可用于在 AudioPlayer 实例之间共享状态 /// 或与音频流代理通信。 ///
public AudioPlayer() { if (!_classInitialized) { _classInitialized = true; // 订阅托管异常处理程序 Deployment.Current.Dispatcher.BeginInvoke(delegate { Application.Current.UnhandledException += AudioPlayer_UnhandledException; }); } } /// 出现未处理的异常时执行的代码 private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached) { // 出现未处理的异常;强行进入调试器 System.Diagnostics.Debugger.Break(); } } ///
/// playstate 更改时调用,但 Error 状态除外(参见 OnError) /// ///
BackgroundAudioPlayer ///
在 playstate 更改时播放的曲目 ///
播放机的新 playstate ///
/// 无法取消播放状态更改。即使应用程序 /// 导致状态自行更改,假定应用程序已经选择了回调。 /// /// 值得注意的 playstate 事件 /// (a) TrackEnded: 播放器没有当前曲目时激活。代理可设置下一曲目。 /// (b) TrackReady: 音轨已设置完毕,现在可以播放。 /// /// 只在代理请求完成之后调用一次 NotifyComplete(),包括异步回调。 ///
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState) { switch (playState) { case PlayState.TrackEnded: player.Track = GetPreviousTrack(); break; case PlayState.TrackReady: player.Play(); break; case PlayState.Shutdown: // TODO: 在此处理关机状态(例如保存状态) break; case PlayState.Unknown: break; case PlayState.Stopped: break; case PlayState.Paused: break; case PlayState.Playing: break; case PlayState.BufferingStarted: break; case PlayState.BufferingStopped: break; case PlayState.Rewinding: break; case PlayState.FastForwarding: break; } NotifyComplete(); } ///
/// 在用户使用应用程序/系统提供的用户界面请求操作时调用 /// ///
BackgroundAudioPlayer ///
用户操作期间播放的曲目 ///
用户请求的操作 ///
与请求的操作相关联的数据。 /// 在当前版本中,此参数仅适合与 Seek 操作一起使用, /// 以指明请求的乐曲的位置 ///
/// 用户操作不自动对系统状态进行任何更改;如果用户操作受支持, /// 执行用户操作(如果这些操作受支持)。 /// /// 只在代理请求完成之后调用一次 NotifyComplete(),包括异步回调。 ///
protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param) { switch (action) { case UserAction.Play: if (player.PlayerState != PlayState.Playing) { player.Play(); } break; case UserAction.Stop: player.Stop(); break; case UserAction.Pause: player.Pause(); break; case UserAction.FastForward: player.FastForward(); break; case UserAction.Rewind: player.Rewind(); break; case UserAction.Seek: player.Position = (TimeSpan)param; break; case UserAction.SkipNext: player.Track = GetNextTrack(); break; case UserAction.SkipPrevious: AudioTrack previousTrack = GetPreviousTrack(); if (previousTrack != null) { player.Track = previousTrack; } break; } NotifyComplete(); } ///
/// 实现逻辑以获取下一个 AudioTrack 实例。 /// 在播放列表中,源可以是文件、Web 请求,等等。 /// ///
/// AudioTrack URI 确定源,它可以是: /// (a) 独立存储器文件(相对 URI,表示独立存储器中的路径) /// (b) HTTP URL(绝对 URI) /// (c) MediaStreamSource (null) ///
///
AudioTrack 实例,或如果播放完毕,则返回 null
private AudioTrack GetNextTrack() { // TODO: 添加逻辑以获取下一条音轨 if (++currentTrackNumber >= _playList.Count) currentTrackNumber = 0; AudioTrack track = _playList[currentTrackNumber]; // 指定曲目 return track; } ///
/// 实现逻辑以获取前一个 AudioTrack 实例。 /// ///
/// AudioTrack URI 确定源,它可以是: /// (a) 独立存储器文件(相对 URI,表示独立存储器中的路径) /// (b) HTTP URL(绝对 URI) /// (c) MediaStreamSource (null) ///
///
AudioTrack 实例,或如果不允许前一曲目,则返回 null
private AudioTrack GetPreviousTrack() { // TODO: 添加逻辑以获取前一条音轨 if (--currentTrackNumber < 0) currentTrackNumber = _playList.Count - 1; AudioTrack track = _playList[currentTrackNumber]; // 指定曲目 return track; } ///
/// 每次播放出错(如 AudioTrack 未正确下载)时调用 /// ///
BackgroundAudioPlayer ///
出现错误的曲目 ///
出现的错误 ///
如果为 true,则播放不能继续并且曲目播放将停止 ///
/// 不保证在所有情况下都调用此方法。例如,如果后台代理程序 /// 本身具有未处理的异常,则不会回调它来处理它自己的错误。 ///
protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal) { if (isFatal) { Abort(); } else { NotifyComplete(); } } ///
/// 取消代理请求时调用 /// ///
/// 取消请求后,代理需要 5 秒钟完成其工作, /// 通过调用 NotifyComplete()/Abort()。 ///
protected override void OnCancel() { } }

最后,我们在mainpage中添加对播放的控制。

[XAML]
[C#]
public partial class MainPage : PhoneApplicationPage    {        // 构造函数        public MainPage()        {            InitializeComponent();            BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);        }        //刚加载时确定播放状态        protected override void OnNavigatedTo(NavigationEventArgs e)        {            if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)            {                button1.Content = "■";                textblock1.Text = "曲目:" + BackgroundAudioPlayer.Instance.Track.Title                    + " 艺术家:" + BackgroundAudioPlayer.Instance.Track.Artist                    + " 专辑:" + BackgroundAudioPlayer.Instance.Track.Album                    + " 曲目长度:" +BackgroundAudioPlayer.Instance.Track.Duration.Minutes + ":" + BackgroundAudioPlayer.Instance.Track.Duration.Seconds;                    using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())                    {                        var stream = storage.OpenFile(BackgroundAudioPlayer.Instance.Track.AlbumArt.OriginalString, System.IO.FileMode.Open);                        var bitmapImage = new BitmapImage();                        bitmapImage.SetSource(stream);                        imge1.Source = bitmapImage;                        stream.Close();                    }            }            else            {                button1.Content = "▶";                textblock1.Text = "未播放曲目";            }        }        void Instance_PlayStateChanged(object sender, EventArgs e)        {            switch (BackgroundAudioPlayer.Instance.PlayerState)            {                case PlayState.Playing:                    button1.Content = "■";                    button2.IsEnabled = true;                    button3.IsEnabled = true;                    break;                case PlayState.Paused:                case PlayState.Stopped:                    button1.Content = "▶";                    break;            }            if (null != BackgroundAudioPlayer.Instance.Track && BackgroundAudioPlayer.Instance.PlayerState!= PlayState.Stopped)            {                textblock1.Text = "曲目:" + BackgroundAudioPlayer.Instance.Track.Title                    + " 艺术家:" + BackgroundAudioPlayer.Instance.Track.Artist                    + " 专辑:" + BackgroundAudioPlayer.Instance.Track.Album                    + " 曲目长度:" + BackgroundAudioPlayer.Instance.Track.Duration.Minutes + ":" + BackgroundAudioPlayer.Instance.Track.Duration.Seconds;                    using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())                    {                        var stream = storage.OpenFile(BackgroundAudioPlayer.Instance.Track.AlbumArt.OriginalString, System.IO.FileMode.Open);                        var bitmapImage = new BitmapImage();                        bitmapImage.SetSource(stream);                        imge1.Source = bitmapImage;                        stream.Close();                    }            }        }        //播放/暂停        private void Button_Click_1(object sender, RoutedEventArgs e)        {            if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)                BackgroundAudioPlayer.Instance.Pause();            else                BackgroundAudioPlayer.Instance.Play();        }        //向前        private void Button_Click_2(object sender, RoutedEventArgs e)        {            BackgroundAudioPlayer.Instance.SkipPrevious();            button2.IsEnabled = false;        }        //向后        private void Button_Click_3(object sender, RoutedEventArgs e)        {            BackgroundAudioPlayer.Instance.SkipNext();            button3.IsEnabled = false;        }    }

 

四、后台文件传输

后台文件传输允许我们实现下载上传文件的功能,他限制系统中同时运行的传输任务不能超过两个,并且下载的文件只能存放在本地文件夹的/shared/transfers目录下。下面我们实现一个后台传输任务,下载博客相册中的一张照片。

[XAML]
[C#]
public partial class MainPage : PhoneApplicationPage    {        // 构造函数        public MainPage()        {            InitializeComponent();        }        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)        {            initTransferRequest();            base.OnNavigatedTo(e);        }        private void initTransferRequest()        {            //获取第一个后台传输任务            var transferRequest = BackgroundTransferService.Requests.FirstOrDefault();            if (transferRequest == null)            {                textblock1.Text = "无后台传输任务";                button1.IsEnabled = true;                return;            }            //当传输状态改变时:            transferRequest.TransferStatusChanged += new EventHandler
(transfer_TransferStatusChanged); //当传输进度改变时: transferRequest.TransferProgressChanged += new EventHandler
(transfer_TransferProgressChanged); updatesStatus(transferRequest); button1.IsEnabled = false; } void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e) { updatesStatus(e.Request); } void transfer_TransferProgressChanged(object sender, BackgroundTransferEventArgs e) { updatesStatus(e.Request); } void updatesStatus(BackgroundTransferRequest transferRequest) { textblock1.Text = "传输状态:" + transferRequest.TransferStatus.ToString() + " 已下载字节:" + transferRequest.BytesReceived + "总字节:" + transferRequest.TotalBytesToReceive; } private void Button_Click_1(object sender, RoutedEventArgs e) { string fileurlstring = "http://images.cnblogs.com/cnblogs_com/lipan/319399/o_Large.png"; Uri uri = new Uri(Uri.EscapeUriString(fileurlstring), UriKind.RelativeOrAbsolute); BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(uri); transferRequest.Method = "GET"; using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) { if (!isoStore.DirectoryExists("/shared/transfers")) { isoStore.CreateDirectory("/shared/transfers"); } } //文件下载后存放位置(为本地文件夹相对位置) transferRequest.DownloadLocation = new Uri("shared/transfers/1.png", UriKind.RelativeOrAbsolute); //外接电源、WiFi的可用性对传输的影响 transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery; try { //添加到后台传输队列中 BackgroundTransferService.Add(transferRequest); } catch (Exception ex) { MessageBox.Show("无法添加后台传输请求。" + ex.Message); } initTransferRequest(); } //清除传输队列已完成的任务 private void Button_Click_2(object sender, RoutedEventArgs e) { foreach (var transferRequest in BackgroundTransferService.Requests) { if (transferRequest.TransferStatus == TransferStatus.Completed) { try { BackgroundTransferService.Remove(transferRequest); } catch { } } } initTransferRequest(); } }

 

五、后台辅助线程

后台辅助线程虽然名字这么叫,但是它不能在后台运行,我们可以用它来执行一个任务,并且可以实时获取执行的进度,实现代码如下:

[XAML]
[C#]
public partial class MainPage : PhoneApplicationPage    {                      private BackgroundWorker bw = new BackgroundWorker();          public MainPage()        {            InitializeComponent();            bw.WorkerReportsProgress = true;            bw.WorkerSupportsCancellation = true;            bw.DoWork += new DoWorkEventHandler(bw_DoWork);            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);        }        private void buttonStart_Click(object sender, RoutedEventArgs e)        {            if (bw.IsBusy != true)            {                bw.RunWorkerAsync();            }        }        private void buttonCancel_Click(object sender, RoutedEventArgs e)        {            if (bw.WorkerSupportsCancellation == true)            {                bw.CancelAsync();            }        }        private void bw_DoWork(object sender, DoWorkEventArgs e)        {            BackgroundWorker worker = sender as BackgroundWorker;            for (int i = 1; i <= 10; i++)            {                if ((worker.CancellationPending == true))                {                    e.Cancel = true;                    break;                }                else                {                    // Perform a time consuming operation and report progress.                    System.Threading.Thread.Sleep(500);                    worker.ReportProgress(i * 10);                }            }        }        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)        {            if (e.Cancelled == true)            {                this.tbProgress.Text = "Canceled!";            }            else if (!(e.Error == null))            {                this.tbProgress.Text = ("Error: " + e.Error.Message);            }            else            {                this.tbProgress.Text = "Done!";            }        }        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)        {            this.tbProgress.Text = (e.ProgressPercentage.ToString() + "%");        }    }

 

作者:[ ]
出处:[ ]
版权声明:本文的版权归作者与博客园共有。转载时须注明原文出处以及作者,并保留原文指向型链接,不得更改原文内容。否则作者将保留追究其法律责任。

转载于:https://www.cnblogs.com/lipan/archive/2013/06/06/3093163.html

你可能感兴趣的文章
003.第一个动画:绘制直线
查看>>
K2BPM怎么让金融数据更有意义?
查看>>
史玉柱自述:我是如何带队伍的
查看>>
靶形数独【贪心+深搜】
查看>>
读大道至简第三章有感
查看>>
BeforeFieldInit的小叙
查看>>
TeamViewer的下载地址,低调低调
查看>>
005 线程ID和线程的优先级
查看>>
POJ 3067 Japan (树状数组 && 控制变量)
查看>>
python基础条件和循环
查看>>
an exciting trip
查看>>
【转】xmind8 破解激活教程
查看>>
Mysql用命令方式启动服务
查看>>
【贪心】codeforces A. Heidi and Library (easy)
查看>>
【leetcode】lower_bound
查看>>
跨站请求伪造(CSRF)
查看>>
EF Code First数据库映射规则及配置
查看>>
.Net StackFrame
查看>>
Qt 学习之路:视图选择 (QItemSelectionModel)
查看>>
QStyleFactory类参考
查看>>