2010/07/02(Fri) 21:15:37 編集(投稿者)
■No51357 (kato(s) さん) に返信
> 因みにグレープシティ社製の、Component1 Studio 2008J の
> C1ToolBarとそれに追加した、C1CommandLinkを使用した場合に現象が発生します。
スタックトレースをみる限りはC1CommandHolderがダメなように見えますね。
>>何をイメージしているのかしら?
>
> それぞれのメソッド内でスレッドで動くような処理を書きたくないので、各画面から
> 汎用的に、既存のメソッドをスレッドで動くように呼び出せないかと考えています。
>
> public void ShowMessageDialog(string a){....}
> public void ShowOpenDialog(string a, bool b){....}
> public void ShowSaveDialog(string a, bool b, bool c){....}
のように、GUIを表示するメソッドの場合、
モードレスであるべきかモーダルであるべきか、他のウィンドウとの関係を再検討したほうがよいと思います。
どうしても他のモーダルウィンドウに邪魔されたくないのであればそれだけ別スレッドで表示するべきでしょう。
そういったウィンドウがたくさんになる場合はそれほど無いと思います。
> public DataTable MethodA(string a, string){....}
> public DataRow MethodB(string a, string bool c){....}
> public int MethodC(DataTable a, string b, bool c){....}
GUIは必要なく、多少時間がかかるだけのメソッドであればDelegateを使えばいいでしょう。
> RunMethodByThreadという汎用的なメソッドを定義して、
> RunMethodByThread(MethodA)、RunMethodByThread(MethodB)のような形で
> メソッドを呼びだせないかという事です。このとき戻り値はどのように
> 受け取れるかなども不明です。
> ※スレッドプールを使用しない場合、やはり各メソッド毎にスレッドで
> 呼出しするためのメソッドを作成しないといけない事になるのでしょうか?
そんなに何種類ものdelegate型が必要になる場合はほとんどないので、
普通は呼びだす関数毎にdelegate型の派生クラスを作成します。
.Net標準のスレッドプールを使う場合でも、普通は各関数毎にdelegate型を作成して使います。
ですが、べつにそうでなくとも構いません。
例えばいま適当に作ってみると…
Public Class AsyncInvoke
Private value As Object = Nothing
Private Sub SetReturnValue(ByVal obj As Object)
SyncLock Me
value = obj
End SyncLock
End Sub
Public Function IsBusy() As Boolean
SyncLock Me
Return value Is Nothing
End SyncLock
End Function
Public Function ReturnValue() As Object
SyncLock Me
Return value
End SyncLock
End Function
Public Shared Function RunMethodByThread(ByVal target As Object, ByVal methodname As String, ByVal arguments As Object()) As AsyncInvoke
Dim st As New Threading.Thread(AddressOf ThreadStartPoint)
Dim n As New AsyncInvoke
st.Start(New Object() {target, methodname, arguments, n})
Return n
End Function
Private Shared Sub ThreadStartPoint(ByVal arg As Object)
Dim args As Object() = DirectCast(arg, Object())
Dim target As Object = DirectCast(args(0), Object)
Dim methodname As String = DirectCast(args(1), String)
Dim d As [Delegate] = [Delegate].CreateDelegate(target.GetType, target, methodname)
Dim arguments As Object() = DirectCast(args(2), Object())
Dim n As AsyncInvoke = DirectCast(args(2), AsyncInvoke)
n.SetReturnValue(d.DynamicInvoke(arguments))
End Sub
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ai As AsyncInvoke = AsyncInvoke.RunMethodByThread(Me, "SampleFunction", New Object() {"parameter1", "parameter2", 3, 4})
While ai.IsBusy
System.Threading.Thread.Sleep(100)
End While
MessageBox.Show(ai.ReturnValue.ToString)
End Sub
というような感じでリフレクション+遅延バインディング+Delegateを使えば
オブジェクトと関数名、パラメーターを指定して別スレッドによる呼び出しが行えます。
戻り値も取得できます。
もちろん、スレッドプールを使っても同様に作れます。