为什么我不能在WPF中通过System.Threading.Timer调用使用CapturePhotoToStreamAsync? [英] Why can't I use CapturePhotoToStreamAsync from a System.Threading.Timer call back in WPF?
问题描述
我在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屋!