###前提・実現したいこと
初心者です。
単純なミスか根本的な部分での勘違いだと思うのですが…例外がスローされて困っています。
ヒント、試してみたらいいこと、検索すべきワード、勉強すべき点などなんでも良いのでご教示願います。
c#でボタンをクリックした時にラベルの文字を変更したいです。
Form1とForm2があります。
Form1にボタンを4つ、Form2にラベル4つを配置しています。
###発生している問題・エラーメッセージ
4つのボタンをランダムに連打をすると例外が出て止まってしまいます。
System.AccessViolationException はユーザー コードによってハンドルされませんでした。
HResult=-2147467261
Message=保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
Source=System.Drawing
StackTrace:
場所 System.Drawing.SafeNativeMethods.Gdip.GdipMeasureString(HandleRef graphics, String textString, Int32 length, HandleRef font, GPRECTF& layoutRect, HandleRef stringFormat, GPRECTF& boundingBox, Int32& codepointsFitted, Int32& linesFilled)
場所 System.Drawing.Graphics.MeasureString(String text, Font font, SizeF layoutArea, StringFormat stringFormat)
場所 System.Windows.Forms.Label.GetPreferredSizeCore(Size proposedConstraints)
場所 System.Windows.Forms.Control.GetPreferredSize(Size proposedSize)
場所 System.Windows.Forms.Label.GetPreferredSize(Size proposedSize)
場所 System.Windows.Forms.Control.get_PreferredSize()
場所 System.Windows.Forms.Label.AdjustSize()
場所 System.Windows.Forms.Label.OnTextChanged(EventArgs e)
場所 System.Windows.Forms.Control.set_Text(String value)
場所 System.Windows.Forms.Label.set_Text(String value)
場所 LifeCounter.Worker.bw_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) 場所~
場所 System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
場所 System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
InnerException:
###該当のソースコード
C#
1 2Form1 3 4 public partial class Form1 : Form 5 { 6 //ボタンやラベル、int iなどそれぞれ同じものが4つ 7 8 Worker wk = new Worker(); 9 int i1 = 0; 10 11 public Form1() 12 { 13 InitializeComponent(); 14 Form2.Instance.Show(); 15 } 16 17 private void button1_MouseDown(object sender, MouseEventArgs e) 18 { 19 if (wk.bw.IsBusy != true) 20 { 21 22 i1++;//4つそれぞれここの動きが違う。増えたり減ったり。 23 wk.bw.RunWorkerAsync(i1); 24 } 25 } 26 } 27 28 29 30
C#
1 2Worker.cs 3 4 class Worker 5 { 6 public BackgroundWorker bw = new BackgroundWorker(); 7 8 public Worker() 9 { 10 bw.DoWork += new DoWorkEventHandler(bw_DoWork); 11 bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 12 13 } 14 private void bw_DoWork(object sender, DoWorkEventArgs e) 15 { 16 e.Result = (int)e.Argument; 17 18 } 19 private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 20 { 21 int result = (int)e.Result; 22 23 try 24 { 25 //ここで例外が発生する 26 Form2.Instance.label1.Text = Convert.ToString(result); 27 //表示が4つそれぞれ違う。i1のときlabel1,i2のときlabel2.. 28 } 29 catch (Exception ex) 30 { 31 Console.WriteLine("キャッチ:{0}", ex); 32 } 33 } 34 35 } 36
###試したこと
Form2.Instance.label1.Text = Convert.ToString(result);
で例外が発生する他、Program.csの
Application.Run(new Controller_Form());
でも発生することがあります。
try catchも書いてみましたが特に何の反応もありません。
自分なりに調べた結果、スレッドセーフな呼び出しとFormを1つだけ表示させるようにしました。
はじめは以下の通り、直接書き換えようとしました。
c#
1private void btn_Click(object sender, MouseEventArgs e) 2 { 3 i++; 4 Form2.Instance.label1.Text = i.ToString(); 5 }
Invokeとdelegateを使ってみましたが、やはり連打すると止まってしまいました。
c#
1 int i1 = 0; 2 delegate void TestDelegate(int i); 3 4 internal void change(int i) 5 { 6 Form2.Instance.lbl_1.Text = Convert.ToString(i.ToString()); 7 } 8 9 10 private void button1_MouseDown(object sender, MouseEventArgs e) 11 { 12 i1++; 13 Invoke(new TestDelegate(change), i1); 14 }
###補足情報(言語/FW/ツール等のバージョンなど)
Visual Studio 2015で開発しています。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/04/10 10:45