.NET でマルチスレッドにしてlabelを変化させるには?

解決


POPO  2007-01-02 17:27:45  No: 64140  IP: 192.*.*.*

表題のことがどうしても出来ません。
ttp://dobon.net/vb/melma/dotnet25.txt
を参考にしてC++ようにしてみたつもりなのですが
エラーで"有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロールがアクセスされました。"
と出てしまいます。
どのようにしたらいいのでしょうか?
サンプルなどがあったら教えていただきたいです。
よろしくお願いいたします。

編集 削除
Blue  2007-01-03 00:47:03  No: 64141  IP: 192.*.*.*

どんなコードを書いていますか?

示されたサイトにも書いてありますが、InvokeRequired をしらべて
Invokeメソッドを呼ぶ必要があります。

参考
http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html

一応VB.NETでサンプルを書いたことはあるので参考になれば。
http://rararahp.cool.ne.jp/cgi-bin/lng/dotnet/dotnetlng.cgi?print+200611/06110002.txt

編集 削除
Blue  2007-01-03 01:30:19  No: 64142  IP: 192.*.*.*

ちなみに、VS2005ならば、Background Workerオブジェクトをつかうと
カナリ便利です。

参考(VB2005)
http://www.atmarkit.co.jp/fdotnet/vb2005/vb2005_04/vb2005_04_01.html

編集 削除
POPO  2007-01-03 02:58:56  No: 64143  IP: 192.*.*.*

>どんなコードを書いていますか?
一番初めに挙げた所のをC++にしただけです。
すみません実はいろいろ試したんですがReleaseでしたら動きました。
ただこれだと
private int AddString(string str)
{
    TextBox1.AppendText(str + "\r\n");
    return TextBox1.Lines.Length;
}
↑(VBですが)ひとつのラベルごと関数が必要になってしまいます。

ですのでBackground Workerのほうを試したのですが
private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {
this->backgroundWorker1->RunWorkerAsync();
     }
private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {

int i;
for(i=0;i<30;i++){
this->label1->Text=i.ToString();
this->label1->Update();
System::Threading::Thread::Sleep((1000));
}
これでlabel1は変わってくれません。

編集 削除
POPO  2007-01-03 03:45:50  No: 64144  IP: 192.*.*.*

そもそもこれをする必要があるのかもわからないので、
しようと思ってることを書きます。

データーとして構造体にint timeとint idとint dataを準備して
time時間経過後にidによってlabel1やlabel2を対象に
そのtextをdataに変えようと思ってます。
時間経過までの間でもボタン等の操作はしたいのでマルチスレッドについて
調べています。

編集 削除
Blue  2007-01-03 15:08:24  No: 64145  IP: 192.*.*.*

普通にタイマーコントロールを使うべきかと思います。

編集 削除
Blue  2007-01-03 15:13:10  No: 64146  IP: 192.*.*.*

ちなみに
>private: System::Void button4_Click(System::Object^  sender, System::EventArgs^  e) {
>this->backgroundWorker1->RunWorkerAsync();
> }
>private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {
>
>int i;
>for(i=0;i<30;i++){
>this->label1->Text=i.ToString();
>this->label1->Update();
>System::Threading::Thread::Sleep((1000));
>}
試しましたが、ちゃんと変わりますよ。

編集 削除
POPO  2007-01-03 16:14:38  No: 64147  IP: 192.*.*.*

>タイマーコントロールを使うべき

ありがとうございます調べてみます。

>試しましたが、ちゃんと変わりますよ。
うーん、私のほうでは動きません。

この頃、インテリセンスが使えなくなったりブレークポイントが
勝手に無効になったり、マウスポインターあてても宣言がみれないので
私のPCの問題ですね。再インストールもしてみます。
ありがとうございました。

編集 削除
Blue  2007-01-03 16:34:52  No: 64148  IP: 192.*.*.*

>うーん、私のほうでは動きません。
まっさらな状態(新規プロジェクト)から、そのコードだけ入れても
ダメでしょうか?

>インテリセンスが使えなくなったり
VS2005のインテリセンスって、なんか使いづらいですね。
PCの性能によるんでしょうが、私もなかなか出てこないときがあります。
ちょっと待つと(プロパティウィンドウを右に表示しているのですが、そこが正しく表示される?と)有効になるようです。

編集 削除
POPO  2007-01-03 17:46:09  No: 64149  IP: 192.*.*.*

>まっさらな状態(新規プロジェクト)から、そのコードだけ入れても
>ダメでしょうか?
まっさらで試して、初め動きませんでしたが
デバックなしだと動きました。

インテリセンスの件他の方もそうなんですね。

これで完成にまた一歩近づくことができました。
ありがとうございます。

編集 削除