为什么我不能在WPF中使用System.Threading.Timer回调的CapturePhotoToStreamAs

本文关键字:Threading System Timer 回调 CapturePhotoToStreamAs 不能 WPF 为什么 | 更新日期: 2023-09-27 18:06:59

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

类型为'System '的第一次异常。MyAssembly.dll

出现异常

附加信息:当前状态下请求无效。

开始

我可以创建一个for循环来执行该方法1000次,它将工作,但是,如果从计时器回调中调用该方法,它会爆炸。

所以澄清一下,代码将在WinForms中的Timer回调中工作该代码将在计时器回调中在WPF中爆炸如果没有在计时器回调中执行,代码将在WPF中工作。

我怀疑这个问题与它正在执行的线程有关,但是,我已经尝试使用Dispatcher,但无济于事。

这里是被调用的方法:

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上是否允许。

为什么我不能使用CapturePhotoToStreamAsync从System.Threading.Timer回调WPF?

为什么我不能在WPF中使用System.Threading.Timer回调的CapturePhotoToStreamAs

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

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