为什么我不能在WPF中通过System.Threading.Timer调用使用CapturePhotoToStreamAsync? [英] Why can't I use CapturePhotoToStreamAsync from a System.Threading.Timer call back in WPF?

查看:245
本文介绍了为什么我不能在WPF中通过System.Threading.Timer调用使用CapturePhotoToStreamAsync?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在WinForms应用程序中有代码,我在其中使用WinRT MediaCapture对象从设备的相机拍摄照片.该代码在System.Threading.Timer回调中执行.我正在尝试将此代码移到WPF中,但遇到了问题.当我尝试从WPF中的计时器回调执行MediaCapture.CapturePhotoToStreamAsync时,收到以下异常:

I have code in a WinForms application where I'm using the WinRT MediaCapture object to take a picture from the device's camera. The code is executed in a System.Threading.Timer call back. I'm trying to move this code into WPF but I'm running into problems. When I try to execute the MediaCapture.CapturePhotoToStreamAsync from the timer's callback in WPF, I receive the following exception:

MyAssembly.dll中发生了'System.Exception'类型的第一次机会异常

A first chance exception of type 'System.Exception' occurred in MyAssembly.dll

其他信息:该请求在当前状态下无效.

Additional information: The request is invalid in the current state.

开始

我可以创建一个for循环来执行该方法1000次,它会起作用,但是,如果从Timer回调中调用该方法,则会产生爆炸.

I can create a for loop to execute the method 1000 times and it will work, however, it bombs if the method is called from within a Timer callback.

因此请澄清一下,该代码将在Timer回调的WinForms中工作 该代码将在Timer回调中在WPF中轰炸 如果未在计时器回调中执行该代码,则该代码将在WPF中工作.

So to clarify, the code will work in WinForms in a Timer callback The code will bomb in WPF in a Timer callback The code will work in WPF if it's not executed in a timer callback..

我怀疑问题与它正在执行的线程有关,但是,我尝试使用分派器无济于事.

I suspect that the issue has something to do with the thread that it's executing on, however, I've tried to use the Dispatcher to no avail.

这是被称为的方法:

public async Task CapturePhoto(int width, int height)
    {
        Thread.Sleep(100);
        var jpgProperties = ImageEncodingProperties.CreateJpeg();
        jpgProperties.Width = (uint)width;
        jpgProperties.Height = (uint)height;

        using (var randomAccessStream = new InMemoryRandomAccessStream())
        {
            if (_MediaCaptureManager != null)
            {
                await _MediaCaptureManager.CapturePhotoToStreamAsync(jpgProperties, randomAccessStream);
                randomAccessStream.Seek(0);
                using (var ioStream = randomAccessStream.AsStream())
                {
                    var bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = ioStream;
                    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                    bitmapImage.EndInit();

                    // copy to byte array
                    int stride = bitmapImage.PixelWidth * 4;
                    byte[] buffer = new byte[stride * bitmapImage.PixelHeight];
                    bitmapImage.CopyPixels(buffer, stride, 0);

                    // create bitmap
                    System.Drawing.Bitmap bitmap =
                        new System.Drawing.Bitmap(
                            bitmapImage.PixelWidth,
                            bitmapImage.PixelHeight,
                            System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                    // lock bitmap data
                    System.Drawing.Imaging.BitmapData bitmapData =
                        bitmap.LockBits(
                            new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                            System.Drawing.Imaging.ImageLockMode.WriteOnly,
                            bitmap.PixelFormat);

                    // copy byte array to bitmap data
                    System.Runtime.InteropServices.Marshal.Copy(
                        buffer, 0, bitmapData.Scan0, buffer.Length);

                    // unlock
                    bitmap.UnlockBits(bitmapData);

                    ImageBrush backgroundBrush = new ImageBrush();
                    backgroundBrush.ImageSource = bitmapImage;

                    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
                    {
                        PreviewPanel.Background = backgroundBrush;
                    }));
                }
            }
        }
    }

我有一个小的WPF项目,如果有帮助,可以通过OneDrive共享.我不想默认包含URL,因为我不确定SO上是否允许.

I have a small WPF project that I can share via OneDrive if that will help. I don't want to include the URL by default because I'm not sure if that is allowed on SO.

为什么我不能在WPF中通过System.Threading.Timer回叫使用CapturePhotoToStreamAsync?

Why can't I use CapturePhotoToStreamAsync from a System.Threading.Timer call back in WPF?

推荐答案

您需要确保CapturePhotoToStreamAsync在UI线程上执行.

You'll need to make sure that the CapturePhotoToStreamAsync is executed on the UI thread.

您应该使用DispatcherTimer而不是Threading.Timer类.

You should use the DispatcherTimer rather than a Threading.Timer class.

这篇关于为什么我不能在WPF中通过System.Threading.Timer调用使用CapturePhotoToStreamAsync?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆