BackgroundWorkerで「ソースは利用できません。」となることについて への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
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/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 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 09:51:06
時間のかかる処理を、バックグランドで処理させようとしています。
の部分に来ると
「ソースは利用できません。
……
TargetInvocationExceptionはハンドルされませんでした。
型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が
mscorlib.dll で発生しました。」
となって目的を達せられないでいます。
どういうことなのか教えていただけないでしょうか。
For Each f As String In files
Dim dir As String = IO.Path.GetDirectoryName(f)
Dim file As String = IO.Path.GetFileName(f)
Dim shell As New Shell
Dim fldr As Folder = shell.NameSpace(dir)
Dim item As FolderItem = fldr.ParseName(file)
Dim artist As String = StrConv(fldr.GetDetailsOf(item, 13), VbStrConv.Narrow)
Dim title As String = StrConv(fldr.GetDetailsOf(item, 21), VbStrConv.Narrow)
Dim cdTitle As String = StrConv(fldr.GetDetailsOf(item, 14), VbStrConv.Narrow)
data.Add(f & "," & artist & "," & title & "," & cdTitle)
Next
の部分に来ると
「ソースは利用できません。
……
TargetInvocationExceptionはハンドルされませんでした。
型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が
mscorlib.dll で発生しました。」
となって目的を達せられないでいます。
どういうことなのか教えていただけないでしょうか。
・Classを利用し、Newコンストラクタで渡す
・ParameterizedThreadStart
②スレッドの終了では
・Joinメソッド
>終了通知用のデリゲート インスタンスを事前に渡しておき、
>終了時にワーカースレッドから呼び出すようにしては如何でしょう。
だと思うんだけど、DelegateとInvokeを利用して
色々と試してみて、大変勉強になりました。
魔界の仮面弁士さん、どうもありがとうございます。