実現したいこと
PowerShellを用いて、USBカメラデバイスの入力映像をリアルタイムにモニタリングすることを考えています。
awaitクラスは、.Netのasync関数の戻り値(__ComObject)をtaskに変換してその実行を待機することを目的に作ってみました。
発生している問題・分からないこと
① .Net の async関数 の戻り値(__ComObject)を実行待機するクラス(await)にて、1回目のコール(InitializeAsync)は通るのに、2回目のコール(StartPreviewAsync)で不明なエラーが発生します。
② 上記のStartPreviewAsyncを待機しないで次に進もうとすると、スレッドのエラーが出ました。
書き換え前:[await]::Action($capture.InitializeAsync(), [object])
書き換え後:$capture.InitializeAsync()
エラーメッセージ
error
1① 2"0" 個の引数を指定して "Wait" を呼び出し中に例外が発生しました: "1 つ以上のエラーが発生しました。" 3+ $netTask.Wait() 4 5② 6"0" 個の引数を指定して ".ctor" を呼び出し中に例外が発生しました: "アプリケーションは、別のスレッドにマーシャリングされたインターフェイスを呼び出しました。 7 (HRESULT からの例外:0x8001010E (RPC_E_WRONG_THREAD))" 8+ $ui.Content = [CaptureElement]::new()
該当のソースコード
PowerShell
1# using namespace 2using namespace System.Windows 3using namespace Windows.Foundation 4using namespace Windows.Media.Capture 5using namespace Windows.UI.Xaml.Controls 6 7# using dotnet 8using assembly PresentationFramework 9using assembly System.Runtime.WindowsRuntime 10 11# import Runtime type [TypeName, AssemblyName, ContentType] 12[Windows.Foundation.IAsyncAction, Windows.Foundation, ContentType=WindowsRuntime] 13[Windows.Media.Capture.MediaCapture, Windows.Media.Capture, ContentType=WindowsRuntime] 14[Windows.UI.Xaml.Controls.CaptureElement, Windows.UI.Xaml.Controls, ContentType=WindowsRuntime] 15 16# init MediaCapture 17$capture = [Mediacapture]::new() 18[await]::Action($capture.InitializeAsync(), [object]) 19 20 # ui 21$ui = [Window]::new() 22$ui.Dispatcher.Invoke([Action]{ 23 $ui.Content = [CaptureElement]::new() 24 $ui.Content.Source = $capture 25 [await]::Action($capture.StartPreviewAsync(), [object]) 26}) 27$ui.ShowDialog() 28 29# awaiter class 30class await{ 31 static [object]Action([__ComObject]$async, [type]$type){ 32 $asTask = [WindowsRuntimeSystemExtensions].GetMethod("AsTask", [IAsyncAction]) 33 $netTask = $asTask.Invoke($null, @($async)) 34 $netTask.Wait() 35 return $netTask.Result 36 } 37}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
$ui.Content = [CaptureElement]::new()
$ui.Content.Source = $capture
[await]::Action($capture.StartPreviewAsync(), [object])
もともとはここは普通に実行していたところを、uiのdispatcherのinvokeで実行するように変更しましたが、効果はありませんでした。
補足
特になし

あなたの回答
tips
プレビュー