C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: 別スレッドでフォームを開いた場合に日本語入力ができない


(過去ログ 86 を表示中)

[トピック内 20 記事 (1 - 20 表示)]  << 0 >>

■51327 / inTopicNo.1)  別スレッドでフォームを開いた場合に日本語入力ができない
  
□投稿者/ kato(s) (1回)-(2010/07/02(Fri) 10:33:51)

分類:[C#] 

kato(s)です。

メインスレッドから別スレッドを作成して、
そのスレッド上で別フォームを開くのですが、
そのフォームで日本語入力ができません。
Windows Vista / Windows 7 で現象が発生します。
※WindowsXPでは発生しません。

以下の単純なコードで現象が発生します。
なにか単純な間違いをしていますでしょうか?
アドバイス・回避策あればよろしくお願いいたします。

環境
C#
Visual Studio 2008 Version 9.0.30729.1 SP
Microsoft Office IME 2010

■メインスレッド(メインフォーム)
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(ThreadMethod));

t.Start();
}

private void ThreadMethod()
{
Form2 f = new Form2();

f.ShowDialog();
}

■別スレッド(Form2:別スレッド)
TextBoxコントロールを貼り付けるだけ
1.半角/全角 漢字キーでIMEモードが変更されない(その後、TextBoxへの入力ができなくなる)
2.デザイナでImeModeプロパティをHiraganaに設定していても、TextBoxへの入力が全くできない

以上、よろしくお願いいたします。

引用返信 編集キー/
■51328 / inTopicNo.2)  Re[1]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ 囚人 (514回)-(2010/07/02(Fri) 11:20:27)
2010/07/02(Fri) 11:22:04 編集(投稿者)

そもそも論になりますけど、別スレッドでフォームを作る必要ありますか?

めったに(というかほぼ100%)別スレッドでフォームを作る必要はないですけど。
引用返信 編集キー/
■51329 / inTopicNo.3)  Re[1]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ Hongliang (660回)-(2010/07/02(Fri) 11:23:32)
TSF のせいかな? だとしたら Thread の ApartmentState を STA にする必要があるでしょう。
しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。
引用返信 編集キー/
■51330 / inTopicNo.4)  Re[2]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ マサヤ (60回)-(2010/07/02(Fri) 12:13:33)
画面を同時に、ってどのような仕様ですか?
単純にシングルスレッドでよいような気がします。

>なにか単純な間違いをしていますでしょうか?
設計になるのでしょうか。。。
引用返信 編集キー/
■51331 / inTopicNo.5)  Re[2]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ kato(s) (2回)-(2010/07/02(Fri) 12:39:11)
kato(s)です。返信ありがとうございました。

> ■囚人 さん
> そもそも論になりますけど、別スレッドでフォームを作る必要ありますか?
> めったに(というかほぼ100%)別スレッドでフォームを作る必要はないですけど。

そもそものお話をさせて頂くと、
業務アプリケーションを開発してるのですが、
1プロセスで複数の画面を同時に開いて操作できるアプリを開発しています。
(1画面1プロセスにすると画面間の連携・オブジェクトの共有等が難しいので)

各画面での処理は独立性が高いので、シングルスレッドの場合、
例えば、A画面で長い処理の実行中や、メッセージダイアログ、
ファイル保存ダイアログなどのダイアログ系が表示されていると、
別で開いているB画面が操作できなくなってしまいますので、それは回避したいです。

それなので、長い処理や各ダイアログの表示処理を別スレッドで動かすことを
考えましたが、対象の業務ロジックとダイアログ表示のためのメソッドが、
数百以上存在するので、全てをスレッドで動かすための処理を書くのは現実的に
厳しいし煩雑なので、フォームを別スレッドで開くための汎用的なメソッドを作成し、
フォーム丸ごと別スレッドにしてしまえば業務ロジックはスレッドを意識しなくても書ける
ということを考えていました。

引数や戻り値が異なるメソッドを別スレッドとして、汎用的に呼び出せる仕組みが
あれば問題ないのですが、それは出来なさそうでしたので、フォームを別スレッドで
開くための汎用的なメソッドの作成を検討した次第です。


> ■Hongliang さん
> TSF のせいかな? だとしたら Thread の ApartmentState を STA にする必要があるでしょう。
> しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。

ApartmentState.STAに設定するとIMEの件は動作しました。
しかし複数のフォームを別スレッドで表示・操作を繰り返していると、
アプリケーションが異常終了してしまいます(動作が不安定)

> しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。

やはり上記が原因になるのでしょうか?
そもそもフォーム丸ごと別スレッドで動かかす仕組みは現実的でないのでしょうか?


以上、よろしくお願いいたします。

引用返信 編集キー/
■51333 / inTopicNo.6)  Re[3]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ 囚人 (515回)-(2010/07/02(Fri) 12:51:08)
2010/07/02(Fri) 12:52:27 編集(投稿者)

>そもそもフォーム丸ごと別スレッドで動かかす仕組みは現実的でないのでしょうか?

そうですね。複雑になるだけで特にメリットはないかと。



>例えば、A画面で長い処理の実行中や

長い処理「だけ」をUIスレッドとは別にする。

>ファイル保存ダイアログなどのダイアログ系が表示されていると、
>別で開いているB画面が操作できなくなってしまいますので、

そんなことないでしょう。
B画面をどう開いているのか知りませんが、同一スレッドだからといって、そういう制限が入ることはありません。


何十、何百と画面を開いたとしても、一つのUIスレッドでまかなえますよ。というか、そうすべきです。

メインループを長くロックするような処理は行わない、わかりやすく言えばUIコンポーネントのイベントハンドラでは処理をすぐ終える、という事を意識すれば、基本的には問題ありません。

引用返信 編集キー/
■51334 / inTopicNo.7)  Re[4]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ よねKEN (535回)-(2010/07/02(Fri) 13:36:42)
よねKEN さんの Web サイト
#では、どうすればいいか、という案は持ち合わせていないのですが・・・

No51333 (囚人 さん) に返信
> >ファイル保存ダイアログなどのダイアログ系が表示されていると、
> >別で開いているB画面が操作できなくなってしまいますので、
>
> そんなことないでしょう。
> B画面をどう開いているのか知りませんが、同一スレッドだからといって、そういう制限が入ることはありません。

新規プロジェクトを作って確認してみましたが、ファイル保存ダイアログが開いていると
同一exeの他のフォームも操作できなくなりますね。

[新規プロジェクトの概要と確認手順]
Form1〜Form3を用意し、Form1からForm2、Form3をShowできるようにボタンを2つ配置
Form2にはSaveFileDialogを表示するためのボタンを1つ配置。
以下の手順で確認しました。

(1)Form1のボタン1をクリック→Form2のShowの呼び出し
(2)Form1のボタン2をクリック→Form3のShowの呼び出し
(3)Form2のボタン1→SaveFileDialogのShowDialogの呼び出し
(4)SaveFileDialog以外はすべて触れない

引用返信 編集キー/
■51335 / inTopicNo.8)  Re[2]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ れい (941回)-(2010/07/02(Fri) 14:06:14)
No51329 (Hongliang さん) に返信
> しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。

そんなことはありません。
作成したthread以外のスレッドでwindowをいじってはいけないという制約はありますが、
複数スレッドでスレッド毎にウィンドウは可能です。

その場合、FileDialogなどModal Windowはスレッド毎になります。


No51331 (kato(s) さん) に返信
> 引数や戻り値が異なるメソッドを別スレッドとして、汎用的に呼び出せる仕組みが
> あれば問題ないのですが、それは出来なさそうでしたので、フォームを別スレッドで
> 開くための汎用的なメソッドの作成を検討した次第です。

Delegateを作成してBeginInvokeでいいのではありませんか?

> ApartmentState.STAに設定するとIMEの件は動作しました。
> しかし複数のフォームを別スレッドで表示・操作を繰り返していると、
> アプリケーションが異常終了してしまいます(動作が不安定)

フォームやコントロールを作成したスレッドが操作する場合、ほとんど問題がありません。
(以前ここで報告したようにInvokeでごく稀に落ちるけど。
他のスレッドが作成したフォーム・コントロールを操作すると振る舞いがおかしくなります。


> そもそもフォーム丸ごと別スレッドで動かかす仕組みは現実的でないのでしょうか?

いいえ。
私も複数のアプリケーションをまとめる際などに使います。

同期が大変なだけで、何も問題はありません。
それがないとモーダルウィンドウの表示でとても困ります。


引用返信 編集キー/
■51337 / inTopicNo.9)  Re[3]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ 渋木宏明 (11回)-(2010/07/02(Fri) 14:35:48)
渋木宏明 さんの Web サイト
>>しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。
>
> そんなことはありません。

のはずですね。

サードパーティ製のコントロールなど含めて、個々のコントロールの実装に問題がある場合はあり得ますが。

引用返信 編集キー/
■51340 / inTopicNo.10)  Re[4]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ 囚人 (516回)-(2010/07/02(Fri) 15:33:48)
No51334 (よねKEN さん) に返信
> #では、どうすればいいか、という案は持ち合わせていないのですが・・・
>
>
> 新規プロジェクトを作って確認してみましたが、ファイル保存ダイアログが開いていると
> 同一exeの他のフォームも操作できなくなりますね。

あぁ本当ですね。失礼しました。前言撤回します。


独立性が高いなら、その独立区分で別プロセスにした方がいいんじゃないかな。
1画面1プロセスか1画面1スレッドの二択にするから困るんじゃない?

引用返信 編集キー/
■51344 / inTopicNo.11)  Re[4]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ kato(s) (3回)-(2010/07/02(Fri) 15:45:17)
2010/07/02(Fri) 15:48:13 編集(投稿者)

■れい さん
>> ApartmentState.STAに設定するとIMEの件は動作しました。
>> しかし複数のフォームを別スレッドで表示・操作を繰り返していると、
>> アプリケーションが異常終了してしまいます(動作が不安定)
>>
>フォームやコントロールを作成したスレッドが操作する場合、ほとんど問題がありません。
>(以前ここで報告したようにInvokeでごく稀に落ちるけど。
>他のスレッドが作成したフォーム・コントロールを操作すると振る舞いがおかしくなります。

■渋木宏明 さん
> >>しかしそれ以前に、UI スレッドを複数に分けるべきではありません。WinForm では考慮されてない状態ですし。
>>
>>そんなことはありません。
>
> のはずですね。
>
> サードパーティ製のコントロールなど含めて、個々のコントロールの実装に問題がある場合はあり得ますが。
>

異常終了する原因ですが調査の結果、
サードパーティ製のコントロールが原因だと思われます。

Aスレッドのフォームで長い処理を実行中に、
Bスレッドのフォームをアクティブにして、サードパーティ製の
ツールバーコントロールにフォーカスがある(マウスのカーソルを当てている)状態で、
Aスレッドの処理が終わった際に、
"有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'xxToolBar1' がアクセスされました。"
のエラーになります。

これはやはり、サードパーティのコントロールの問題なので、
アプリケーション側で回避策は不可能なものでしょうか?

Aスレッドの処理の最後に、FormA.Activate(); を書くとエラーにならないようですが、
全ての処理の最後で、FormA.Activate(); を書くのも現実的ではありません。


■れい さん
>> 引数や戻り値が異なるメソッドを別スレッドとして、汎用的に呼び出せる仕組みが
>> あれば問題ないのですが、それは出来なさそうでしたので、フォームを別スレッドで
>> 開くための汎用的なメソッドの作成を検討した次第です。
>
>Delegateを作成してBeginInvokeでいいのではありませんか?

こちらは、これから汎用的な呼出が可能か試してみます。
ただし、BeginInvokeメソッドは、スレッドプール使用するので、
CPU毎に25スレッドまでの制限があると書いてあったのですが、
制限を広げたりはできないのでしょうか?

以上、よろしくお願いいたします。

引用返信 編集キー/
■51345 / inTopicNo.12)  Re[5]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ kato(s) (4回)-(2010/07/02(Fri) 15:55:06)
■囚人 さん
>>#では、どうすればいいか、という案は持ち合わせていないのですが・・・
>>
>>
>>新規プロジェクトを作って確認してみましたが、ファイル保存ダイアログが開いていると
>>同一exeの他のフォームも操作できなくなりますね。
>
> あぁ本当ですね。失礼しました。前言撤回します。
>
>
> 独立性が高いなら、その独立区分で別プロセスにした方がいいんじゃないかな。
> 1画面1プロセスか1画面1スレッドの二択にするから困るんじゃない?

プロセスは分けたくないと考えています。
ログイン情報や、シングルトンのオブジェクトを別プロセス間で
簡単に共有できる良い方法が見つからなかったので・・。
逆にプロセス間で簡単にオブジェクトの共有ができればそれでも良いと思っています。
※今からアプリケーションの構成を大きく変えるのは、かなり難しいと思っていますが(汗)

引用返信 編集キー/
■51347 / inTopicNo.13)  Re[5]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ れい (942回)-(2010/07/02(Fri) 16:25:45)
No51344 (kato(s) さん) に返信
> これはやはり、サードパーティのコントロールの問題なので、
> アプリケーション側で回避策は不可能なものでしょうか?

それだけの情報では何とも言えません。

普通コントロールは再利用可能なようにカプセル化されたものですから、独立性が高いものです。
ですので、参照するのは親ウィンドウ程度、多くても親の親ウィンドウ、そのメニュー程度だと期待できます。

よほど特殊か、複雑なコントロールでない限り、
他のスレッドの作成したウィンドウ・コントロールを参照することはないはずです。
サードパーティのコントロールということはある程度汎用性のあるコントロールのはずですから、特殊ではありません。
複雑なことをするコントロールなのでしたら、
他スレッドのコントロールを操作してはいけないことぐらい考えているでしょう。

ですので、サードパーティのコントロールを疑うのは後でしょう。

例えば
・アプリケーションの全ウィンドウを列挙して色を設定する
・アプリケーションのメインウィンドウのメニューを変更する
というような機能をもったコントロールであるなら
疑いが大きくなると思います。

私なら、自分の書いたコードを疑います。

> ■れい さん
> >> 引数や戻り値が異なるメソッドを別スレッドとして、汎用的に呼び出せる仕組みが
> >> あれば問題ないのですが、それは出来なさそうでしたので、フォームを別スレッドで
> >> 開くための汎用的なメソッドの作成を検討した次第です。
> >
> >Delegateを作成してBeginInvokeでいいのではありませんか?
>
> こちらは、これから汎用的な呼出が可能か試してみます。
> ただし、BeginInvokeメソッドは、スレッドプール使用するので、
> CPU毎に25スレッドまでの制限があると書いてあったのですが、
> 制限を広げたりはできないのでしょうか?

アクティブなスレッドが25というだけで残りはキューに入れることが可能です。
それで問題になるような場合はスレッドプールを使うのが間違いと考えた方がよいでしょう。
プロセッサの時分割はコストの高い処理ですので。

スレッドプールは基本的には小さい作業を細切れに実行するのに向いています。
kato(s)さんの用途には向いていないかもしれません。
大きい作業をさせるなら、個別にthreadを作成したほうが実行効率も見通しもよくなります。
引用返信 編集キー/
■51348 / inTopicNo.14)  Re[6]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ kato(s) (5回)-(2010/07/02(Fri) 16:55:35)
■れい さん
>>これはやはり、サードパーティのコントロールの問題なので、
>>アプリケーション側で回避策は不可能なものでしょうか?
>
> それだけの情報では何とも言えません。
>
> 普通コントロールは再利用可能なようにカプセル化されたものですから、独立性が高いものです。
> ですので、参照するのは親ウィンドウ程度、多くても親の親ウィンドウ、そのメニュー程度だと期待できます。
>
> よほど特殊か、複雑なコントロールでない限り、
> 他のスレッドの作成したウィンドウ・コントロールを参照することはないはずです。
> サードパーティのコントロールということはある程度汎用性のあるコントロールのはずですから、特殊ではありません。
> 複雑なことをするコントロールなのでしたら、
> 他スレッドのコントロールを操作してはいけないことぐらい考えているでしょう。
>
> ですので、サードパーティのコントロールを疑うのは後でしょう。
>
> 例えば
> ・アプリケーションの全ウィンドウを列挙して色を設定する
> ・アプリケーションのメインウィンドウのメニューを変更する
> というような機能をもったコントロールであるなら
> 疑いが大きくなると思います。
>
> 私なら、自分の書いたコードを疑います。

切り分けのために、単純なコードを書いて動作確認しています。

1.メインスレッドから別スレッドでフォームを作成

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(ThreadMethod));

t.SetApartmentState(ApartmentState.STA);

t.Start();
}
private void ThreadMethod()
{
Form2 f = new Form2();

f.ShowDialog();
}

2.別スレッドのForm2でのButton1をクリック

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 15000; i++)
{
Debug.Print(i.ToString());
}
}

3.メインスレッド(メインフォーム)をアクティブにして、
  メインフォームに貼り付けた、xxToolBarにマウスを持っいき、
  ツールバーのボタンがハイライトされた状態にする。

4.別スレッドのButton1の処理が終わると例外が発生。

■コードは上に上げたものしか書いていませんのでサードパーティのコントロールかなと・・
※両方のフォームにxxToolBarを配置している場合のみ発生し、メインフォームにだけ、
xxToolBarを配置している場合は例外は発生しません。


>>>> 引数や戻り値が異なるメソッドを別スレッドとして、汎用的に呼び出せる仕組みが
>>>> あれば問題ないのですが、それは出来なさそうでしたので、フォームを別スレッドで
>>>> 開くための汎用的なメソッドの作成を検討した次第です。
>>>
>>>Delegateを作成してBeginInvokeでいいのではありませんか?
>>
>>こちらは、これから汎用的な呼出が可能か試してみます。
>>ただし、BeginInvokeメソッドは、スレッドプール使用するので、
>>CPU毎に25スレッドまでの制限があると書いてあったのですが、
>>制限を広げたりはできないのでしょうか?
>
> アクティブなスレッドが25というだけで残りはキューに入れることが可能です。
> それで問題になるような場合はスレッドプールを使うのが間違いと考えた方がよいでしょう。
> プロセッサの時分割はコストの高い処理ですので。
>
> スレッドプールは基本的には小さい作業を細切れに実行するのに向いています。
> kato(s)さんの用途には向いていないかもしれません。
> 大きい作業をさせるなら、個別にthreadを作成したほうが実行効率も見通しもよくなります。

キューに入るのであれば、制限は問題なさそうです。
今回の処理のスレッド化の目的は、スレッドでの処理で小さい作業を細切れにすることではなく、
長い処理の実行中やダイアログ系が開いた場合に他の画面を固まらないようにするためです。

> 大きい作業をさせるなら、個別にthreadを作成したほうが実行効率も見通しもよくなります。

最初の疑問に戻ってしまい申し訳ありませんが、個別にthreadを作成するのであれば、
様々な引数・戻り値のメソッドを汎用的な呼び出しでスレッドで動かすことは無理ですよね?

以上、よろしくお願いいたします。

引用返信 編集キー/
■51349 / inTopicNo.15)  Re[7]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ れい (943回)-(2010/07/02(Fri) 17:26:42)
No51348 (kato(s) さん) に返信
> ■コードは上に上げたものしか書いていませんのでサードパーティのコントロールかなと・・

最近は「書いたコード」だけだと情報として十分ではありません。
GUIの操作手順や、どの会社のなんというコントロールをどう使ったのか、
というような情報も出せばだれかが何かヒントをくれるかもしれません。

開発元に聞け、というのも手ですし。

> キューに入るのであれば、制限は問題なさそうです。
> 今回の処理のスレッド化の目的は、スレッドでの処理で小さい作業を細切れにすることではなく、
> 長い処理の実行中やダイアログ系が開いた場合に他の画面を固まらないようにするためです。

ならスレッドプールで無い方がよいと思います。

> 最初の疑問に戻ってしまい申し訳ありませんが、個別にthreadを作成するのであれば、
> 様々な引数・戻り値のメソッドを汎用的な呼び出しでスレッドで動かすことは無理ですよね?

「様々な引数・戻り値のメソッドを汎用的な呼び出しでスレッドで動かす」というのが
どういうことなのか私にはよくわかりません。

汎用的というのはどういうことでしょうか?

私の知っている、スレッド処理のある全ての言語で
別スレッドでどんなメソッドも呼べますし、
その際にどんな引数を与えることも可能で、
終了時にはどんな結果でも返すことが可能です。

.Netであるならデリゲートが使えますので
どのメソッドをどう呼ぶのかというメタデータを
実行時に動的に決定したり保存したりすることも可能です。

何をイメージしているのかしら?
引用返信 編集キー/
■51357 / inTopicNo.16)  Re[8]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ kato(s) (6回)-(2010/07/02(Fri) 19:09:26)
■れい さん
>>■コードは上に上げたものしか書いていませんのでサードパーティのコントロールかなと・・
>
> 最近は「書いたコード」だけだと情報として十分ではありません。
> GUIの操作手順や、どの会社のなんというコントロールをどう使ったのか、
> というような情報も出せばだれかが何かヒントをくれるかもしれません。
>
> 開発元に聞け、というのも手ですし。

開発元には現在確認中(回答待ち)です。
因みにグレープシティ社製の、Component1 Studio 2008J の
C1ToolBarとそれに追加した、C1CommandLinkを使用した場合に現象が発生します。

■前提条件
Form1(起動フォーム),Form2を作成
それぞれのフォームにButtonコントロールを貼り付け
それぞれのフォームにC1ToolBarコントロールを貼り付け
それぞれのフォームのC1ToolBarコントロール上に任意のC1CommandLinkを追加

■操作手順
1.Form1が起動します
2.Form1上のボタン(button1)を押下します。
 private void button1_Click(object sender, EventArgs e)
 {
  Thread t = new Thread(new ThreadStart(ThreadMethod));
  t.Start();
 }
 private void ThreadMethod()
 {
  Form2 f = new Form2();
  f.ShowDialog();
 }
3.Form2が別スレッドで起動します。
4.Form2上のボタン(button1)を押下します。
 private void button1_Click(object sender, EventArgs e)
 {
  for (int i = 0; i < 15000; i++)
  {
   Debug.Print(i.ToString());
  }
 }
5.4.の処理中にForm1をクリックし、Form1をアクティブにします。
6.マウスカーソルをForm1上のC1CommandLinkの上に持っていきます(C1CommandLinkがハイライトされます)
7.4.の処理が終了するまで6.の状態を維持します。
8.4.の処理の終了時に以下の例外が発生します。

■有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'c1ToolBar1' がアクセスされました。
場所 System.Windows.Forms.Control.get_Handle()
場所 System.Windows.Forms.Control.PointToClientInternal(Point p)
場所 System.Windows.Forms.Control.PointToClient(Point p)
場所 C1.Win.C1Command.C1ToolBar.C1.Win.C1Command.IBarInternal.ContainsScreenPoint(Point p)
場所 C1.Win.C1Command.C1CommandHolder.j(Object A_0, EventArgs A_1)
場所 System.EventHandler.Invoke(Object sender, EventArgs e)
場所 System.Windows.Forms.Form.OnDeactivate(EventArgs e)
場所 System.Windows.Forms.Form.set_Active(Boolean value)
場所 System.Windows.Forms.Form.WmActivate(Message& m)
場所 System.Windows.Forms.Form.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.RunDialog(Form form)
場所 System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
場所 System.Windows.Forms.Form.ShowDialog()
場所 WindowsFormsApplication2.Form1.ThreadMethod() 場所 D:\WindowsFormsApplication2\WindowsFormsApplication2\Form1.cs:行 31
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()


>>キューに入るのであれば、制限は問題なさそうです。
>>今回の処理のスレッド化の目的は、スレッドでの処理で小さい作業を細切れにすることではなく、
>>長い処理の実行中やダイアログ系が開いた場合に他の画面を固まらないようにするためです。
>
> ならスレッドプールで無い方がよいと思います。
>
>>最初の疑問に戻ってしまい申し訳ありませんが、個別にthreadを作成するのであれば、
>>様々な引数・戻り値のメソッドを汎用的な呼び出しでスレッドで動かすことは無理ですよね?
>
> 「様々な引数・戻り値のメソッドを汎用的な呼び出しでスレッドで動かす」というのが
> どういうことなのか私にはよくわかりません。
>
> 汎用的というのはどういうことでしょうか?
>
> 私の知っている、スレッド処理のある全ての言語で
> 別スレッドでどんなメソッドも呼べますし、
> その際にどんな引数を与えることも可能で、
> 終了時にはどんな結果でも返すことが可能です。
>
> .Netであるならデリゲートが使えますので
> どのメソッドをどう呼ぶのかというメタデータを
> 実行時に動的に決定したり保存したりすることも可能です。
>
> 何をイメージしているのかしら?

非常にわかりにくくて申し訳ございません。

既存のメソッド、
public DataTable MethodA(string a, string){....}
public DataRow MethodB(string a, string bool c){....}
public int MethodC(DataTable a, string b, bool c){....}
public void ShowMessageDialog(string a){....}
public void ShowOpenDialog(string a, bool b){....}
public void ShowSaveDialog(string a, bool b, bool c){....}
のような、スレッドで動かないメソッドが数百程度あるとします。

それぞれのメソッド内でスレッドで動くような処理を書きたくないので、各画面から
汎用的に、既存のメソッドをスレッドで動くように呼び出せないかと考えています。

例えば、
RunMethodByThreadという汎用的なメソッドを定義して、
RunMethodByThread(MethodA)、RunMethodByThread(MethodB)のような形で
メソッドを呼びだせないかという事です。このとき戻り値はどのように
受け取れるかなども不明です。
※スレッドプールを使用しない場合、やはり各メソッド毎にスレッドで
呼出しするためのメソッドを作成しないといけない事になるのでしょうか?

スレッド関連について知識が乏しく、わかりにくい表現になってしまい申し訳ありません。

以上、よろしくお願いいたします。

引用返信 編集キー/
■51362 / inTopicNo.17)  Re[9]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ れい (944回)-(2010/07/02(Fri) 21:15:23)
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を使えば
オブジェクトと関数名、パラメーターを指定して別スレッドによる呼び出しが行えます。
戻り値も取得できます。
もちろん、スレッドプールを使っても同様に作れます。

引用返信 編集キー/
■51367 / inTopicNo.18)  Re[9]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ 渋木宏明 (12回)-(2010/07/02(Fri) 22:44:36)
渋木宏明 さんの Web サイト
>  private void button1_Click(object sender, EventArgs e)
>  {
>   for (int i = 0; i < 15000; i++)
>   {
>    Debug.Print(i.ToString());
>   }
>  }

そもそもで言うと、このいわゆる「重い処理」をワーカースレッドや BackgroundWorker を使って、UI スレッドとは別に実行するのが、より望ましい(≒ UI スレッドはなるべくブロックしない)パターンです。

まぁ、モーダルダイアログ対策などで Form を別スレッドで開かなくてはならないかもしれませんが。。。
引用返信 編集キー/
■51372 / inTopicNo.19)  Re[6]: 別スレッドでフォームを開いた場合に日本語入力ができない
□投稿者/ なちゃ (457回)-(2010/07/02(Fri) 23:38:08)
参考までに、GrapeCityのいくつかのコンポーネントは、こういう使い方をすると不具合を起こしました。
現行の製品がどうかは知りませんが、その時は回避策はなしでした。

それ以外では問題が発生した記憶はないですね。
※スレッド起動した側は、Application.Runしてましたけどね。
引用返信 編集キー/
■51447 / inTopicNo.20)  Re[10]: 別スレッドでフォームを開いた場合に日本語入力ができない
 
□投稿者/ kato(s) (7回)-(2010/07/06(Tue) 13:44:56)
■れい さん
>>因みにグレープシティ社製の、Component1 Studio 2008J の
>>C1ToolBarとそれに追加した、C1CommandLinkを使用した場合に現象が発生します。
>
> スタックトレースをみる限りはC1CommandHolderがダメなように見えますね。

販売元のグレープシティに問い合せたところ、
C1Commandの各コントロールはマルチスレッド上での
利用を考慮していませんとのことでした。

・別スレッド化したい処理(長い処理やダイアログボックスの表示)のみ別スレッドで動かす
・C1Commandを利用しないでフォーム毎のスレッド化を検討

色々と教えて頂いた内容を利用しながら、効率が良く利用しやすい実装方法を
検討してみたいと思います。


■渋木宏明 さん

>>  private void button1_Click(object sender, EventArgs e)
>>  {
>>   for (int i = 0; i < 15000; i++)
>>   {
>>    Debug.Print(i.ToString());
>>   }
>>  }
>
>そもそもで言うと、このいわゆる「重い処理」をワーカースレッドや BackgroundWorker を使って、UI スレッドとは別に実行するのが、より望ま>しい(≒ UI スレッドはなるべくブロックしない)パターンです。
>まぁ、モーダルダイアログ対策などで Form を別スレッドで開かなくてはならないかもしれませんが。。。

UIはメインスレッドでという方向での検討も進めていこうと思います。


■なちゃ さん

> 参考までに、GrapeCityのいくつかのコンポーネントは、こういう使い方をすると不具合を起こしました。
>現行の製品がどうかは知りませんが、その時は回避策はなしでした。
>
>それ以外では問題が発生した記憶はないですね。
>※スレッド起動した側は、Application.Runしてましたけどね。

上にも書きましたが、C1Commandについては、マルチスレッドは考慮していないとの回答を頂きましたので、
あきらめたいと思います。C1Command以外のコントロールはどうか?も確認中ですので、それによっては、
C1Commandだけ使用しないようにするか等も検討しようと考えています。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -