Windows phone 8 (6) multi task learning notes

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Windows phone 8 is a single task operating system, any time there is only one application is active, multi task here refers to the background task support. In this section we'll talk about the running state of the application, and then have a look back office tasks, including: background agent, background audio, background file transfer, background worker thread etc.

Fast navigation:
First, the state of the application
Two, background agent
Three, the background audio
Four, the background file transfer
Five, the worker thread

First, the state of the application

1)Running applications

We through the illustrations to running state analysis of application, application startup and placed in the interface is the only at the running status, other operations, such as the win key, back export application, open the selector and the starter will let the application currently running into the dormant state, if the system is out of memory, in the application of the dormant state may be logical delete. The following diagram illustrates this process.

2)How to restore the state

When the application is in a dormant state, the state information that is still retained in memory, the next time the user account does not have any change switch. But when the application is logically deleted, the state information will be lost, such as form filling content will disappear, in order to avoid this situation, we need to manually keep state information.
First, we define some form controls in a mainpage page:

[XAML]
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBox Text="{Binding TextBox1Text, Mode=TwoWay}" Height="72" HorizontalAlignment="Left" Margin="20,20,0,0" Name="textBox1" VerticalAlignment="Top" Width="440" /> <CheckBox IsChecked="{Binding CheckBox1IsChecked, Mode=TwoWay}" Content="CheckBox" Height="71" Name="checkBox1" Margin="20,100,0,0" VerticalAlignment="Top"/> <Slider Value="{Binding Slider1Value, Mode=TwoWay}" Height="84" Name="slider1" Width="440" Margin="20,180,0,0" VerticalAlignment="Top"/> <RadioButton IsChecked="{Binding RadioButton1IsChecked, Mode=TwoWay}" Content="RadioButton 1" Height="71" Name="radioButton1" GroupName="RadioButtonGroup" Margin="20,260,0,0" VerticalAlignment="Top"/> <RadioButton IsChecked="{Binding RadioButton1IsChecked, Mode=TwoWay}" Content="RadioButton 2" Height="71" Name="radioButton2" GroupName="RadioButtonGroup" Margin="20,340,0,0" VerticalAlignment="Top"/> </Grid>

We need to implement the application logic can be removed after the state is maintained to the State of the page in the dictionary, but we need the data source supports serialization, so we define Association and ViewModel of the form as follows:

[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)); } }

I need to add page navigation, navigation of events to the mainpage code. Navigation page out of time, if not backward navigation, the memory state. When the navigation in, we need to determine if the page is logically deleted after recovering state, if it is, to restore a state by state dictionary. The mainpage code is as follows:

[C#]
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); _isNewPageInstance = true; } ViewModel _viewModel = null; /// <summary> /// New or existing examples examples /// </summary> 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 not backward navigation, save state 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; } }

And then we add a page1 page, the page to add a back button. Used for testing. In order to achieve the debugging instant access to logical delete effect, we need to set the. Right click the project file, attribute, in the debug tab select “ cancel the delete logical activated during debugging”.


Two, background agent

Background agent can be applied after the exit of independent running in the background, it contains two types of agents, are regularly agent and resource intensive agent, the former is used to perform frequent small tasks, which is used for executing a time-consuming task in the system is idle. To use the background agent, we need to add a Windows phone program task agent projects, and in the application of the project to add a reference to it, now we must realize the pop-up in the background agents in Toast, we need the following OnInvoke method to modify the ScheduledAgent.cs, code is as follows

[C#]
protected override void OnInvoke(ScheduledTask task) { string toastMessage = ""; if (task is PeriodicTask) { toastMessage = "Regular agent is running ";} else {toastMessage =" resource intensive agent is running ";} // for display to a user Toast, If the current task of the front running, Don't display: ShellToast toast = new (ShellToast); toast.Title = "title"; toast.Content = toastMessage; toast.Show (); // when debugging the need for timely implementation of view results #if DEBUG_AGENT ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(15)); #endif NotifyComplete(); }

Then, we call in the application project in mainpage agent, the code as follows:

[XAML]
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <StackPanel Orientation="Vertical" Name="PeriodicStackPanel" Margin="0,0,0,40"> <TextBlock Text="Regular agent "Style=" {StaticResource PhoneTextTitle2Style} "/> <StackPanel Orientation=" Horizontal "> <TextBlock Text=" name: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding Name}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The availability of" VerticalAlignment="Center" Style="{StaticResource PhoneTextAccentStyle}"/> <CheckBox Name="PeriodicCheckBox" IsChecked="{Binding IsEnabled}" Checked="PeriodicCheckBox_Checked" Unchecked="PeriodicCheckBox_Unchecked"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Whether the plan: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding IsScheduled}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The running time of the last plan: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding LastScheduledTime}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Planned end time: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding ExpirationTime}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The reasons from the last agent runs: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding LastExitReason}" /> </StackPanel> </StackPanel> <StackPanel Orientation="Vertical" Name="ResourceIntensiveStackPanel" Margin="0,0,0,40"> <TextBlock Text="Resource intensive agent "Style=" {StaticResource PhoneTextTitle2Style} "/> <StackPanel Orientation=" Horizontal "> <TextBlock Text=" name: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding Name}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The availability of" VerticalAlignment="Center" Style="{StaticResource PhoneTextAccentStyle}"/> <CheckBox Name="ResourceIntensiveCheckBox" IsChecked="{Binding IsEnabled}" Checked="ResourceIntensiveCheckBox_Checked" Unchecked="ResourceIntensiveCheckBox_Unchecked"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Whether the plan: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding IsScheduled}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The running time of the last plan: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding LastScheduledTime}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Planned end time: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding ExpirationTime}" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="The reasons from the last agent runs: " Style="{StaticResource PhoneTextAccentStyle}"/> <TextBlock Text="{Binding LastExitReason}" /> </StackPanel> </StackPanel> </StackPanel> </Grid>
[C#]
public partial class MainPage : PhoneApplicationPage { /// <summary> /// Regular agent /// </summary> PeriodicTask periodicTask; /// <summary> /// Resource intensive agent /// </summary> ResourceIntensiveTask resourceIntensiveTask; string periodicTaskName = "PeriodicAgent"; string resourceIntensiveTaskName = "ResourceIntensiveAgent"; public bool agentsAreEnabled = true; // Constructor public MainPage() { InitializeComponent(); } //Start the regular agent private void StartPeriodicAgent() { agentsAreEnabled = true; // Regular agent to obtain the current name, If there is removed periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask; if (periodicTask != null) { RemoveAgent(periodicTaskName); } periodicTask = new PeriodicTask(periodicTaskName); periodicTask.Description = "This is a regular agent description information. "; try { ScheduledActionService.Add(periodicTask); PeriodicStackPanel.DataContext = periodicTask; //When debugging the need for timely implementation of view results #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("The application program is the user disables background. "); 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("The number of regular limit is reached. "); } PeriodicCheckBox.IsChecked = false; } catch (SchedulerServiceException) { PeriodicCheckBox.IsChecked = false; } } private void StartResourceIntensiveAgent() { agentsAreEnabled = true; // Resource intensive agent to obtain the current name, If there is removed resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask; if (resourceIntensiveTask != null) { RemoveAgent(resourceIntensiveTaskName); } resourceIntensiveTask = new ResourceIntensiveTask(resourceIntensiveTaskName); resourceIntensiveTask.Description = "This is a resource intensive agent description information. "; try { ScheduledActionService.Add(resourceIntensiveTask); ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask; //When debugging the need for timely implementation of view results #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("The application program is the user disables background. "); 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); } /// <summary> /// Delete agent /// </summary> 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; } }

Three, the background audio

Through the background audio functions we can play music function in the system background, because the background audio proxy can only access the local folder, so we must first copy need to play music files to a local folder. This example is to copy the installation folder audio files to a local folder, as shown in the following code example:

[C#]
//Copy the installation folder file to a local folder 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); } } } } } }

We need to add the Windows phone audio playback agent project in the solution, and the application in the project to add a reference to it. Modify the AudioPlayer.cs code is as follows:

[C#]
public class AudioPlayer : AudioPlayerAgent { private static volatile bool _classInitialized; private static List<AudioTrack> _playList = new List<AudioTrack> { new AudioTrack(new Uri("Ring01.wma", UriKind.Relative),"Tracks1","Artist1","The album1",new Uri("Ring01.jpg", UriKind.Relative)), new AudioTrack(new Uri("Ring02.wma", UriKind.Relative),"Tracks2","Artist2","The album2",new Uri("Ring02.jpg", UriKind.Relative)), new AudioTrack(new Uri("Ring03.wma", UriKind.Relative),"Tracks3","Artist3","The album3",new Uri("Ring03.jpg", UriKind.Relative)) }; /// <summary> /// The current playback position /// </summary> static int currentTrackNumber = 0; /// <remarks> /// The AudioPlayer instance can share the same process. Public static field can be used for shared state X or flow agent communication and audio in an instance of AudioPlayer. /// </remarks> public AudioPlayer() { if (!_classInitialized) { _classInitialized = true; // Subscription managed exception handler Deployment.Current.Dispatcher.BeginInvoke(delegate { Application.Current.UnhandledException += AudioPlayer_UnhandledException; }); } } /// An unhandled exception occurred during the execution of the code private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached) { // An unhandled exception occurred, 强行进入调试器 System.Diagnostics.Debugger.Break(); } } /// <summary> /// Call the playstate changes, except the Error state (see OnError) /// </summary> /// <param name="player">BackgroundAudioPlayer</param> /// <param name="track">Playback in playstate change tracks</param> /// <param name="playState">The new playstate player </param> /// <remarks> /// Unable to cancel playback state changes. Even if the application just lead to the state change, assume that the application has chosen the callback. /// /// Note the playstate event x (a) TrackEnded: player is not the current track activation. The agent can be set to the next track. /// (b) TrackReady: tracks have been set, can now play. /// /// After the completion of the proxy request only a call NotifyComplete (), including asynchronous callback. /// </remarks> 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: in this treatment the shutdown state (such as save state) 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(); } /// <summary> /// Call in the user application / system provides a user interface for operation /// </summary> /// <param name="player">BackgroundAudioPlayer</param> /// <param name="track">Playing user during operation.</param> /// <param name="action">The user requested operation</param> /// <param name="param">Associated with the requested operation linked data. Just in the current version, this parameter is only suitable for use with the Seek operating, just to indicate the position of the request.</param> /// <remarks> /// The user does not automatically on the system state to make any changes; if the user operation supported, just execute operation (if these operations are supported). X x completed only after the proxy request a call NotifyComplete (), including asynchronous callback. /// </remarks> 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(); } /// <summary> /// The logic for a AudioTrack instance. Just in the playlist, source can be a file, a Web request, etc. /// </summary> /// <remarks> /// AudioTrack URI determine the source, it can be: X (a) independent memory file (relative to the URI, said the path independence in memory) x (b) HTTP URL (absolute URI) /// (c) MediaStreamSource (null) /// </remarks> /// <returns>The AudioTrack instance, or if the finished playing, returns null</returns> private AudioTrack GetNextTrack() { // TODO: Add logic to get the next track if (++currentTrackNumber >= _playList.Count) currentTrackNumber = 0; AudioTrack track = _playList[currentTrackNumber]; // The specified program return track; } /// <summary> /// The logic for a AudioTrack instance. /// </summary> /// <remarks> /// AudioTrack URI determine the source, it can be: X (a) independent memory file (relative to the URI, said the path independence in memory) x (b) HTTP URL (absolute URI) /// (c) MediaStreamSource (null) /// </remarks> /// <returns>The AudioTrack instance, or if not allowed before a repertoire, it returns null</returns> private AudioTrack GetPreviousTrack() { // TODO: Add logic to get previous tracks if (--currentTrackNumber <0) currentTrackNumber = _playList.Count - 1; AudioTrack track = _playList[currentTrackNumber]; // The specified program return track; } /// <summary> /// Each player error (such as AudioTrack is not correctly download) call /// </summary> /// <param name="player">BackgroundAudioPlayer</param> /// <param name="track">The wrong track</param> /// <param name="error">Error</param> /// <param name="isFatal">If true, then play can not continue and playing music will stop</param> /// <remarks> /// Does not guarantee that the method call in all cases. For example, if the agent just has an unhandled exception, no callback to handle its own mistake. /// </remarks> protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal) { if (isFatal) { Abort(); } else { NotifyComplete(); } } /// <summary> /// Call to cancel the proxy request /// </summary> /// <remarks> /// Cancel the request, agent requires 5 seconds to complete its work, just by calling NotifyComplete()/Abort(). /// </remarks> protected override void OnCancel() { } }

Finally, we add in mainpage to broadcast control.

[XAML]
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and the title of the page is --> <StackPanel x:Name= "TitlePanel" Grid.Row= "0" Margin= "12,17,0,28" > <TextBlock x:Name= "ApplicationTitle" Text= "background audio" Style="{StaticResource PhoneTextNormalStyle}"/> </StackPanel> <!--ContentPanel - placing other content -- here> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Button x:Name="button2" Content="〈" HorizontalAlignment="Left" Margin="13,10,0,0" VerticalAlignment="Top" Click="Button_Click_2"/> <Button x:Name="button1" Content="▶" HorizontalAlignment="Left" Margin="75,10,0,0" VerticalAlignment="Top" Click="Button_Click_1"/> <Button x:Name="button3" Content="〉" HorizontalAlignment="Left" Margin="136,10,0,0" VerticalAlignment="Top" Click="Button_Click_3" /> <TextBlock x:Name="textblock1" HorizontalAlignment="Left" Margin="22,87,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> <Image x:Name="imge1" HorizontalAlignment="Left" Height="100" Margin="22,142,0,0" VerticalAlignment="Top" Width="100"/> </Grid> </Grid>
[C#]
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged); } //To determine the state of play just loading protected override void OnNavigatedTo(NavigationEventArgs e) { if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState) { button1.Content = "■"; textblock1.Text = "Tracks: " + BackgroundAudioPlayer.Instance.Track.Title + " Artist: " + BackgroundAudioPlayer.Instance.Track.Artist + " The album: " + BackgroundAudioPlayer.Instance.Track.Album + " The track length: " +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 = "No playlist"; } } 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 = "Tracks: " + BackgroundAudioPlayer.Instance.Track.Title + " Artist: " + BackgroundAudioPlayer.Instance.Track.Artist + " The album: " + BackgroundAudioPlayer.Instance.Track.Album + " The track length: " + 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(); } } } //Play/Pause private void Button_Click_1(object sender, RoutedEventArgs e) { if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState) BackgroundAudioPlayer.Instance.Pause(); else BackgroundAudioPlayer.Instance.Play(); } //Forward private void Button_Click_2(object sender, RoutedEventArgs e) { BackgroundAudioPlayer.Instance.SkipPrevious(); button2.IsEnabled = false; } //Backward private void Button_Click_3(object sender, RoutedEventArgs e) { BackgroundAudioPlayer.Instance.SkipNext(); button3.IsEnabled = false; } }

Four, the background file transfer

The background document transmission allows us to achieve upload and download files, he limited transmission task cannot at the same time system in the operation of more than two, and download the file can only be stored in a local folder under the /shared/transfers directory. Below we achieve a background transmission task, download a photo blog album in the.

[XAML]
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and the title of the page is --> <StackPanel x:Name= "TitlePanel" Grid.Row= "0" Margin= "12,17,0,28" > <TextBlock x:Name= "ApplicationTitle" Text= "background transmission" Style="{StaticResource PhoneTextNormalStyle}"/> </StackPanel> <!--ContentPanel - Place the other content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock x:Name="textblock1" HorizontalAlignment="Left" Margin="10,198,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> <Button Content="Purge completed tasks in the transmission queue" HorizontalAlignment="Left" Margin="0,85,0,0" VerticalAlignment="Top" Click="Button_Click_2"/> </Grid> <Button x:Name="button1" Content="Add a background transmission" HorizontalAlignment="Left" Margin="12,10,0,0" Grid.Row="1" VerticalAlignment="Top" Click="Button_Click_1"/> </Grid>
[C#]
public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { initTransferRequest(); base.OnNavigatedTo(e); } private void initTransferRequest() { //Gets the first background transmission task var transferRequest = BackgroundTransferService.Requests.FirstOrDefault(); if (transferRequest == null) { textblock1.Text = "No background transmission task"; button1.IsEnabled = true; return; } //When the transmission state change: transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged); //When the transmission schedule changes: transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(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 = "Transmission state: " + transferRequest.TransferStatus.ToString() + " The downloaded bytes: " + transferRequest.BytesReceived + "Total bytes: " + 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"); } } //Download the file location(为本地文件夹相对位置) transferRequest.DownloadLocation = new Uri("shared/transfers/1.png", UriKind.RelativeOrAbsolute); //External power supply, WiFiAffected by the availability of transmission transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery; try { //Adding to the background in the transmission queue BackgroundTransferService.Add(transferRequest); } catch (Exception ex) { MessageBox.Show("Unable to add the background transmission request. " + ex.Message); } initTransferRequest(); } //Remove the transmission queue completed tasks 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(); } }

Five, the worker thread

The auxiliary thread although the name calling, but it cannot run in the background, we can use it to perform a task, and can obtain real-time execution progress, implementation of the code are as follows:

[XAML]
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" > <Button x:Name="buttonStart" Content=""Click=" buttonStart_Click "Width=" 200 "/> <Button x:Name=" buttonCancel "Content=" cancel" Click="buttonCancel_Click" Width="200" /> </StackPanel> <StackPanel Margin="10,50,0,0" Orientation="Horizontal"> <TextBlock Text="Speed of progress: " /> <TextBlock x:Name="tbProgress" /> </StackPanel> </StackPanel> </Grid>
[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() + "%"); } }

Author: [Lipan]
Source: []
Copyright statement: the copyright belongs to the author CO and garden blog. Reproduced must indicate the original source and the author, and keep the original point to the link, must not change the content of the original. Otherwise, the author will retain the legal responsibility.
A: Windows phone 8 study notes block and notice a series Directory: Windows phone 8 study notes equipment
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Milly at November 20, 2013 - 5:41 AM