我正在尝试通过Windows Phone应用程序中的TorchControl Class操作手电筒应用程序:这是我的代码
private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desiredCamera)
{
DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredCamera);
if (deviceID != null) return deviceID;
else throw new Exception(string.Format("Camera {0} doesn't exist", desiredCamera));
}
async private void Button_Click(object sender, RoutedEventArgs e)
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
var mediaDev = new MediaCapture();
await mediaDev.InitializeAsync(new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview,
AudioDeviceId = String.Empty,
VideoDeviceId = cameraID.Id
});
var videoDev = mediaDev.VideoDeviceController;
var tc = videoDev.TorchControl;
if (tc.Supported)
tc.Enabled = true;
mediaDev.Dispose();
}
但问题是每次我第二次单击按钮时应用程序都会崩溃。我被告知要使用mediaDev.Dispose()方法,但它也不起作用。以下是例外情况:
类型为"系统异常"的第一次机会异常发生在 mscorlib.ni.dll WinRT 信息:与此错误关联的文本 找不到代码。
- 当"初始化异步"中的文本突出显示时,将显示此内容
MediaCapture 在重新初始化时会抛出异常。要解决此问题,只需确保在导航回相机页面或单击相机按钮时不要初始化 MediaCapture 两次。
MediaCapture mediacapture = new MediaCapture();
bool initialized;
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
if (initialized == false)
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
await mediacapture.InitializeAsync(new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.Photo,
AudioDeviceId = string.Empty,
VideoDeviceId = cameraID.Id
});
}
//Selecting Maximum resolution for Video Preview
var maxPreviewResolution = mediacapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview).Aggregate((i1, i2) => (i1 as VideoEncodingProperties).Height > (i2 as VideoEncodingProperties).Height ? i1 : i2);
//Selecting 4rd resolution setting
var selectedPhotoResolution = mediacapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).ElementAt(3);
await mediacapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, selectedPhotoResolution);
await mediacapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, maxPreviewResolution);
// in my .xaml <CaptureElement Name="viewfinder" />
viewfinder.Source = mediacapture;
mediacapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
await mediacapture.StartPreviewAsync();
initialized = true;
}
此外,请确保相机在您导航到其他页面之前或在相机再次开始预览之前停止预览。没有必要处理MediaCapture。
private async void GoBack_Click(object sender, RoutedEventArgs e)
{
await mediacapture.StopPreviewAsync();
this.Frame.Navigate(typeof(MainPage));
//Not needed
//mediacapture.Dispose();
}
GetCameraID方法归功于Romasz的博客。 http://www.romasz.net/how-to-take-a-photo-in-windows-runtime/
这个问题可能与多线程有关:使用默认值(即不更改SynchronizationContext
)调用await
将继续另一个线程上的方法,图形和媒体库并不总是支持这种情况(我有SFML,WPF和AutoCAD的第一手经验,非常崩溃,仅举几例)。虽然 InitializeAsync
方法的存在表明并非如此,但请确保不需要在主线程等上进行处置。