为什么我不能在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?
您需要确保在UI线程上执行CapturePhotoToStreamAsync
。
您应该使用DispatcherTimer
而不是Threading.Timer
类。