BackgroundWorkerで「ソースは利用できません。」となることについて
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2016/12/12 11:09:14
> 時間のかかる処理を、バックグランドで処理させようとしています。
COM コンポーネントの Shell オブジェクトを利用していますが、
これの ThreadingModel は Apartment となっています。
すなわち、シングルスレッドアパートメント(STA)からしか呼び出せない仕様です。
一方、BackgroundWorker で生成されるスレッドは、常に
マルチスレッドアパートメント(MTA)です。そのため、
BackgroundWorker 内から Shell オブジェクトを使うことはできません。
ひとまず、
Debug.Print( System.Threading.Thread.CurrentThread.GetApartmentState().ToString() )
の内容を確認してください。Shell を呼びたいなら、これが STA でなければなりません。
そして STA なスレッドを用意したいのであれば、BackgroundWorker は使えません。
代わりに、New Thread で生成したスレッドを SetApartmentState することになります。
COM コンポーネントの Shell オブジェクトを利用していますが、
これの ThreadingModel は Apartment となっています。
すなわち、シングルスレッドアパートメント(STA)からしか呼び出せない仕様です。
一方、BackgroundWorker で生成されるスレッドは、常に
マルチスレッドアパートメント(MTA)です。そのため、
BackgroundWorker 内から Shell オブジェクトを使うことはできません。
ひとまず、
Debug.Print( System.Threading.Thread.CurrentThread.GetApartmentState().ToString() )
の内容を確認してください。Shell を呼びたいなら、これが STA でなければなりません。
そして STA なスレッドを用意したいのであれば、BackgroundWorker は使えません。
代わりに、New Thread で生成したスレッドを SetApartmentState することになります。
投稿者 ねぼすけ  (社会人)
投稿日時
2016/12/12 17:01:10
>Debug.Print( System.Threading.Thread.CurrentThread.GetApartmentState().ToString() )
の内容は「MTA」でした。
色々調べて、
Dim th As New Threading.Thread(New Threading.ThreadStart(AddressOf GetCsv))
th.SetApartmentState(Threading.ApartmentState.STA)
th.Start()
で、目的は達せられました。課題もあります。
①BackgroundWorkerでしたら、引数を渡せました。Threadではどうするのか。
②スレッドの終了をどう把握するのか。
です。今、「Delegate」や「Invoke」について調べています。
何か参考になることがあれば教えてください。
の内容は「MTA」でした。
色々調べて、
Dim th As New Threading.Thread(New Threading.ThreadStart(AddressOf GetCsv))
th.SetApartmentState(Threading.ApartmentState.STA)
th.Start()
で、目的は達せられました。課題もあります。
①BackgroundWorkerでしたら、引数を渡せました。Threadではどうするのか。
②スレッドの終了をどう把握するのか。
です。今、「Delegate」や「Invoke」について調べています。
何か参考になることがあれば教えてください。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2016/12/12 18:27:44
> 引数を渡せました。Threadではどうするのか。
こんな感じです。
http://www.atmarkit.co.jp/fdotnet/dotnettips/434paramthread/paramthread.html
> スレッドの終了をどう把握するのか。
終了通知用のデリゲート インスタンスを事前に渡しておき、
終了時にワーカースレッドから呼び出すようにしては如何でしょう。
BackgroundWorker.RunWorkerCompleted のように、イベント通知でも良いですけど。
こんな感じです。
http://www.atmarkit.co.jp/fdotnet/dotnettips/434paramthread/paramthread.html
> スレッドの終了をどう把握するのか。
終了通知用のデリゲート インスタンスを事前に渡しておき、
終了時にワーカースレッドから呼び出すようにしては如何でしょう。
BackgroundWorker.RunWorkerCompleted のように、イベント通知でも良いですけど。
投稿者 ねぼすけ  (社会人)
投稿日時
2016/12/14 13:41:27
①引数の渡し方2種類覚えました。
・Classを利用し、Newコンストラクタで渡す
・ParameterizedThreadStart
②スレッドの終了では
・Joinメソッド
>終了通知用のデリゲート インスタンスを事前に渡しておき、
>終了時にワーカースレッドから呼び出すようにしては如何でしょう。
だと思うんだけど、DelegateとInvokeを利用して
色々と試してみて、大変勉強になりました。
魔界の仮面弁士さん、どうもありがとうございます。
・Classを利用し、Newコンストラクタで渡す
・ParameterizedThreadStart
②スレッドの終了では
・Joinメソッド
>終了通知用のデリゲート インスタンスを事前に渡しておき、
>終了時にワーカースレッドから呼び出すようにしては如何でしょう。
だと思うんだけど、DelegateとInvokeを利用して
色々と試してみて、大変勉強になりました。
魔界の仮面弁士さん、どうもありがとうございます。
の部分に来ると
「ソースは利用できません。
……
TargetInvocationExceptionはハンドルされませんでした。
型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が
mscorlib.dll で発生しました。」
となって目的を達せられないでいます。
どういうことなのか教えていただけないでしょうか。