C# Windows Phone应用程序耗电过多。使用HttpClient

C# Windows Phone应用程序耗电过多。使用HttpClient,c#,windows-phone-8,C#,Windows Phone 8,我正在编写一个应用程序,允许用户控制媒体经典播放器MPC的播放,如暂停/播放、音量增大/减小、同步字幕等。MPC有一个可以激活的Web界面,使这种交互更容易。但有时当我运行和使用这个应用程序时,我的电池会比平时快 我敢肯定,导致电池过度消耗的一个关键特性是定时器。代码如下所述,但为了简短起见,几秒钟后,它会向Web界面重复HttpClient请求,以接收播放器的正确当前时间 我的问题是:我认为HttpClient行为可能会生成过多的请求并堆积,即使应用程序不再运行,这是对的吗?而且,如果Http

我正在编写一个应用程序,允许用户控制媒体经典播放器MPC的播放,如暂停/播放、音量增大/减小、同步字幕等。MPC有一个可以激活的Web界面,使这种交互更容易。但有时当我运行和使用这个应用程序时,我的电池会比平时快

我敢肯定,导致电池过度消耗的一个关键特性是定时器。代码如下所述,但为了简短起见,几秒钟后,它会向Web界面重复HttpClient请求,以接收播放器的正确当前时间

我的问题是:我认为HttpClient行为可能会生成过多的请求并堆积,即使应用程序不再运行,这是对的吗?而且,如果HttpClient不是使用web服务器并与之交互的正确或更好的对象,它会是什么?关于C语言中的请求,我应该知道的建议有:欢迎使用的方法、对象、关于这些对象的书籍等等

该应用程序在名为MainPage.cs的文件中运行。它使用名为Player.cs的类的方法

MainPage.cs:

Player.cs:


我正在做另一个项目,它包含一个运行在后台的计时器。令我惊讶的是,我了解到,当应用程序挂起时,即当锁屏关闭或其他应用程序开始运行时,所有连接、网络请求或计时器都会停止,直到用户返回应用程序,并且如果没有编码,它不会自动重试连接和请求

如果我将PhoneApplicationService.Current.UserIdleDetectionMode=IdleDetectionMode.Disabled设置为;,这将覆盖用户的设置,并防止锁定屏幕,然后我将不得不手动处理所有的计时器和请求保持-


最后,这个应用程序不是问题,HttpClient对象也不是问题。

为什么不暂时用字符串的模拟响应替换频繁的web请求呢?这对性能有什么影响?根据您的描述,与媒体播放相比,web请求似乎不太可能导致性能问题。@WiredPairie该应用程序不控制手机本身媒体的媒体播放。它用来控制一个远程播放器,比如我客厅里的一台电脑,没有键盘/鼠标。该应用程序的目标是用MPC播放控件替换遥控器。模拟字符串将与播放机失去同步,如果用户通过键盘而不是应用程序停止媒体,它将继续计数。如果您无法临时替换web服务调用,我不知道如何帮助。您是否尝试过使用探查器查看是否存在无法解释的CPU使用情况?
namespace homecinemarc
{
    public partial class MainPage : PhoneApplicationPage
    {
        public IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
        // Timer to check movie status is defined here
        public DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(.3) };
        public HttpClient client = new HttpClient();
        private Player player;
        private string filename;

        // Constructor
        public MainPage()
        {
            // Default initialization
            InitializeComponent();

            if (settings.Contains("ip") && settings.Contains("port"))
            {
                player = new Player(settings["ip"] as string, settings["port"] as string);
            }

            if (!DeviceNetworkInformation.IsWiFiEnabled)
            {
                MessageBox.Show("Your phone's wifi is off. To run this app correctly, you must turn it on. You will be redirected to you Windows Phone connectivity settings.");
                ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask();
                connectionSettingsTask.ConnectionSettingsType = ConnectionSettingsType.WiFi;
                connectionSettingsTask.Show();
            }


            // Default Messaging
            connectedMessage.Text = "Connecting to homecinema";
            progressBar.Visibility = Visibility.Visible;           
        }

        /// <summary>
        /// Core code
        /// </summary>
        private async void MainProgram()
        {
            if (await player.checkConnection())
            {

                connectedMessage.Text = "Connected to " + player.ip + ":" + player.port;
                PlayButton.IsEnabled = true;
                PauseButton.IsEnabled = true;

                // Verificar posição do player
                await player.checkStatus();

                // Update with player status;
                barPosition.Maximum = player.totalTime.Ticks;
                barPosition.Value = player.currentTime.Ticks;

                txtCurrentTime.Text = player.currentTime.ToString();
                txtTotalTime.Text = player.totalTime.ToString();

                if (player.status == "Playing")
                {
                    PauseButton.Visibility = Visibility.Visible;
                    PlayButton.Visibility = Visibility.Collapsed;
                }
                else
                {
                    PauseButton.Visibility = Visibility.Collapsed;
                    PlayButton.Visibility = Visibility.Visible;
                }

                timer.Tick += updateTimers;
                timer.Start();
            }
            else
            {
                player.showError(Error.FailedToConnect);
                connectedMessage.Text = "Connection Failed to " + player.ip + ":" + player.port;
            }
            progressBar.Visibility = Visibility.Collapsed;
        }

        /// <summary>
        /// Checks if it's the first run of the app.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            // First run, runs a basic configuration.
            if (!settings.Contains("firstRun"))
            {
                try
                {
                    MessageBox.Show("This is your first run! Let me show how to setup Homecinema correctly. You must tap on Settings by the end of the instructions, set an IP and save it to use this app correctly :)");
                    NavigationService.Navigate(new Uri("/HelpPage.xaml", UriKind.Relative));
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                MainProgram();
            }
        }

        /// <summary>
        /// Update timer values
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void updateTimers(object sender, EventArgs e)
        {
            await player.checkStatus();

            string currentFilename = player.filename;

            // Checks if there is a change of file and reset 
            // subtitle delay value if there is.
            if (filename != currentFilename)
                player.subtitleDelay = 0;

            barPosition.Value = player.currentTime.Ticks;
            txtCurrentTime.Text = player.currentTime.ToString();
            txtStatus.Text = player.status;
            txtVolume.Text = player.volumeValue + "%";
            txtVolume.Foreground = new SolidColorBrush(Colors.White);
            txtFilename.Text = player.filename;
            txtSubtitleValue.Text = player.subtitleDelay + "ms";
            filename = player.filename;

            if (player.volumeMute == 1)
            {
                txtVolume.Text = "Mute";
                txtVolume.Foreground = new SolidColorBrush(Colors.Red);
            }

            if (player.status == "Playing")
            {
                PlayButton.Visibility = Visibility.Collapsed;
                PauseButton.Visibility = Visibility.Visible;
            }
            else
            {
                PauseButton.Visibility = Visibility.Collapsed;
                PlayButton.Visibility = Visibility.Visible;
            }

        }

        /********************************
         * Events 
         ********************************/

        private void Refresh_Click(object sender, EventArgs e)
        {
            connectedMessage.Text = "Connecting to homecinema";
            progressBar.Visibility = Visibility.Visible;

            MainProgram();
        }

        private void Play_Click(object sender, RoutedEventArgs e)
        {
            player.makeRequest("887");
            txtStatus.Text = "Playing";
            timer.Start();
            PlayButton.Visibility = Visibility.Collapsed;
            PauseButton.Visibility = Visibility.Visible;
        }

        private void Pause_Click(object sender, RoutedEventArgs e)
        {
            player.makeRequest("888");
            txtStatus.Text = "Paused";
            PauseButton.Visibility = Visibility.Collapsed;
            PlayButton.Visibility = Visibility.Visible;
        }

        private void btn_volumeMute_Click(object sender, RoutedEventArgs e)
        {
            player.makeRequest("909");
        }

        private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
        {
            player.makeRequest("907");
        }

        // There are some other events but all with the same structure as
        // above.

    }
}
namespace homecinemarc
{
    class Player
    {
        public Connection conn;
        public string ip { get; set; }
        public string port { get; set; }
        public string filename { get; private set; }
        public string status { get; private set; }
        public int volumeValue { get; private set; }
        public int volumeMute { get; private set; }
        public bool isConnected { get; private set; }
        public TimeSpan currentTime;
        public TimeSpan totalTime;
        public int subtitleDelay { get; set; }
        private HttpClient client = new HttpClient();

        // Constructor
        public Player(string ip, string port)
        {
            conn = new Connection(ip, port);
            this.ip = ip;
            this.port = port;
            this.subtitleDelay = 0;
        }

        /// <summary>
        /// Check if there is a connection to defined IP and Port to allow the app to run
        /// </summary>
        public async Task<bool> checkConnection()
        {
            try
            {
                HttpResponseMessage aResponse = await client.GetAsync(new Uri("http://" + ip + ":" + port + "/command.html"));
                isConnected = aResponse.StatusCode.Equals(HttpStatusCode.OK);
                return isConnected;

            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Update variables of timers 
        /// </summary>
        /// <returns></returns>
        public async Task checkStatus()
        {
            HttpResponseMessage aResponse = await client.GetAsync(new Uri("http://" + this.ip + ":" + this.port + "/status.html"));
            string[] match = Regex.Split(aResponse.Content.ReadAsStringAsync().Result, @",");

            if (match.Length > 0){
                TimeSpan.TryParse(match[3].Substring(2, match[3].Length - 3), out currentTime);
                TimeSpan.TryParse(match[5].Substring(2, match[5].Length - 3), out totalTime);
                status = match[1].Substring(2, match[1].Length - 3);
                volumeMute = int.Parse(match[6]);
                volumeValue = int.Parse(match[7]);

                // These next steps try to remove Rippers, file formarts, etc
                // to show a short yet useful name. That's because MPC don't
                // return the media title (like, IDv3 tag), just filename.
                match[0] = HttpUtility.UrlEncode(match[0]);
                match[0] = Regex.Replace(match[0].Substring(12, match[0].Length - 15), "[\\.]|[\\+]", " ");
                match[0] = Regex.Replace(match[0], "Xvid|Ac3|www|org|avi|mp4|mkv|wmv|HDTV|X264|DIMENSION|\\-|\\((\\d+)\\)|%5(d|b)|Dual Audio|BRRip|x264|AC3|1080p|Lektor i Napisy PL|mvgroup|NF|DD5|WEBRip|NTb|\\-", "");

                filename = match[0];
                Debug.WriteLine(filename);
            }
        }

        /// <summary>
        /// Core method that sends POST request to IP and PORT defined
        /// </summary>
        /// <param name="wmcommand">Code defined by MCP controls.html code</param>
        public async void makeRequest(String wmcommand)
        {
            try
            {
                HttpClient client = new HttpClient();
                var body = String.Format("wm_command={0}", wmcommand);

                StringContent theContent = new StringContent(body, System.Text.Encoding.UTF8, "application/x-www-form-urlencoded");
                HttpResponseMessage aResponse = await client.PostAsync(new Uri("http://" + this.ip + ":" + this.port + "/command.html"), theContent);
            }
            catch (Exception e)
            {
                showError(Error.FailedRequest);
            }
        }

        /// <summary>
        /// Shoes a messagebox with error description
        /// </summary>
        /// <param name="error">Error type of sealed values. Seek to Error class to find which is appropriate</param>
        public void showError(Error error)
        {
            MessageBox.Show(error.ToString());
        }
    }
}