Windows Phone 8.1的MediaCapture使手机冻结

23
我想制作一个简单的应用程序,可以让我检查每个预览帧的几个参数,但我在运行和停止预览时遇到了困难。
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        MediaCapture _MediaCapture;
        bool _recording;
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.
        /// This parameter is typically used to configure the page.</param>
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);


            var rearCamera = devices[0];
            if (devices.Count > 0)
            {

                rearCamera = devices.Single(currDev =>
                  currDev.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back
                );
            }

            _MediaCapture = new MediaCapture();
            await _MediaCapture.InitializeAsync(new MediaCaptureInitializationSettings() { VideoDeviceId = rearCamera.Id });

// this is CaptureElement
            xCapture.Source = _MediaCapture;

            _recording = false;
        }

        protected override async void OnNavigatedFrom(NavigationEventArgs e)
        {
            if(_MediaCapture != null)
            {
                await _MediaCapture.StopPreviewAsync();
                await _MediaCapture.StopRecordAsync();

                _MediaCapture.Dispose();
                _MediaCapture = null;

                xCapture.Source = null;
            }


            base.OnNavigatedFrom(e);


        }

// button click handler
        private async void StartMeasure(object sender, RoutedEventArgs e)
        {
            if (_recording)
            {
                //await _MediaCapture.StopPreviewAsync();
                _MediaCapture.VideoDeviceController.TorchControl.Enabled = false;
                _recording = false;
            }
            else
            {
                //await _MediaCapture.StartPreviewAsync();
                _MediaCapture.VideoDeviceController.TorchControl.Enabled = true;
                _recording = true;
            }
        }
    }

这个表单在这种形式下完美地运作。

如果我取消对那些预览行的注释,它可以工作,但仅限于一次。

如果我按按钮三次:打开、关闭和再次打开,我会在启用TorchControl的那一行遇到异常。

System.Exception: Exception from HRESULT: 0xE801000D at Windows.Media.Devices.TorchControl.put_Enabled(Boolean value) at Pulsometr3.MainPage.d__d.MoveNext()

HRESULT的值是不同的。

更奇怪的是,有时它会导致手机冻结(大约三次中有两次),我需要按住电源键+音量减小键才能解决。

我尝试在所有方法上添加[STAThread]修饰符,但没有帮助 (http://technet.microsoft.com/en-ca/br226599)。

更加有趣的是,当我使用F10调试器暂停操作以跳过某些代码行时,我可以随意切换预览。这很奇怪,因为调试器会暂停所有线程,对吧?所以理论上没有区别?

此外,手机有时会在部署时冻结...真烦人。

有什么想法吗?


看起来 await _MediaCapture.StopPreviewAsync() 正在创建一个无限循环,你可以在所有方法中设置断点以查看它是否实际上正在创建一个无限循环。 - Pedro.The.Kid
我有一个类似的问题:我可以运行应用程序一次。它开始捕获所有内容。然后我停止调试。无论我下一次想要使用相机的方式是什么:这个应用程序,wp-qr-code扫描器,照相机应用程序。它都会冻结,我必须重新启动手机。 - ecth
实际上,这似乎与此相关:http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Dn642092%28v=win.10%29.aspx#cleaning_up_mediacapture_resources_properly我仍在努力弄清楚如何完全释放mediaCapture..他们还使用了"(App.Current as App). MediaCapture = _mediaCapture;"。所以有一些全局实例。但是他们没有显示App.xaml.cs代码。。=/ - ecth
当我像他们一样Dispose时,我可以通过任何方式关闭应用程序,但无法停止调试。当我停止调试时,它不会正常结束并杀死当前状态的mediaCapture。因此,下次再次打开相机时,它会冻结手机。在创建新的之前有没有可能检查这个问题? - ecth
我不确定。我个人转向了Windows Phone 8 API,因为我需要取得进展。 - Krzysztof Skowronek
3个回答

1
如果我理解正确,该按钮具有名为StartMeasure的处理程序,它是一个异步方法,并等待Start/StopPreviewAsync()。问题可能在于,如果您单击该按钮超过一次,则一个操作可能仍在等待(进行中),而另一个操作也被调用,这可能会导致一些问题,因为它将尝试同时开始和停止预览,这可能会导致某些竞争条件。您可以通过添加锁来管理对捕获管理器的访问以测试此功能。此外,在等待操作之后检查bool并分配它肯定不是原子操作,因此可能会导致竞争条件。
    private object locker;

    private async void StartMeasure(object sender, RoutedEventArgs e)
    {
        lock (locker)
        {
            if (_recording)
            {
                await _MediaCapture.StopPreviewAsync();
            }
            else
            {
                await _MediaCapture.StartPreviewAsync();
            }
            _recording = !_recording;
            _MediaCapture.VideoDeviceController.TorchControl.Enabled = _recording;               
        }
    }

这可能是事实,但问题已有3年了 :) 现在我无法检查。 - Krzysztof Skowronek

1
我认为你的问题是页面缓存已启用。尝试在代码中删除此行:this.NavigationCacheMode = NavigationCacheMode.Required;

1
我完全陷入了这个问题......由于某种原因,微软并不太关心WP8的后继操作系统,这让我感到非常难过。但也是在半年前的夏天,我尝试过这个方法,也许你可以尝试一下在应用程序同意方面进行谷歌搜索,并仔细检查你的应用程序清单,如果你已经勾选了前/后摄像头和网络摄像头 :) 除此之外,如果它不起作用,那就很遗憾,你必须坚持使用wp 8.0版本,它在wp 8.1上的工作方式完全相同,所以不要担心:) 此外,像Facebook之类的其他库或parse.com在wp 8.1 C#上也无法工作 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接