2009-05-29 12 views
7

次のコードは私に以下のエラーを示しています。私は "InvokeRequired"が必要だと思う。しかし、私はどのように使うことができるのか分かりません。「作成されたスレッド以外のスレッドからアクセスしました」というエラーを修正するにはどうすればよいですか?

クロススレッド操作が無効です: 'listBox1'コントロールが作成されたスレッド以外のスレッドからアクセスされました。

コード:

using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace WindowsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     protected static DataSet dataset = null; 
     private void Form1_Load(object sender, EventArgs e) 
     { 

     } 

     private void timer1_Tick(object sender, EventArgs e) 
     { 
      SimulationFrameWork.MCSDirector run = new SimulationFrameWork.MCSDirector(); 
      DataSet ds = run.Get(); 

      if (ds.Tables[0].Rows.Count > 0) 
      { 
       for (int i = 0; i < ds.Tables[0].Rows.Count; i++) 
       { 
        if (ds.Tables[0].Rows[i]["result"].ToString() == "0") 
        { 
         dataset = run.Get(int.Parse(ds.Tables[0].Rows[i]["ID"].ToString())); 
         WorkerObject worker = 
         new WorkerObject(
          int.Parse(dataset.Tables[0].Rows[i]["ID"].ToString()), 
          int.Parse(dataset.Tables[0].Rows[i]["Iteration"].ToString()), 
          listBox1, timer1); 
         Thread thread1 = new Thread(new ThreadStart(worker.start)); 
         thread1.Start(); 
        } 
       } 
      } 
     } 
    } 

    public class WorkerObject 
    { 
     private int id; 
     private int nmax; 
     private ListBox list1; 
     private System.Windows.Forms.Timer timer1; 

     public WorkerObject(int _id, int _nmax, ListBox _list1, 
          System.Windows.Forms.Timer _timer1) 
     { 
      id = _id; 
      nmax = _nmax; 
      list1 = _list1; 
      timer1 = _timer1; 
     } 
     public void start() 
     { 
      timer1.Stop(); 
      int i, idaire, j; 
      double pi = 0.0, x, y; 

      Random rnd = new Random(); 
      for (i = 0; i < 100; i++) 
      { 
       idaire = 0; 
       for (j = 0; j < nmax; j++) 
       { 
        x = rnd.Next(1, 10000)/(double)10000; 
        y = rnd.Next(1, 10000)/(double)10000; 
        if (Math.Pow(x, 2) + Math.Pow(y, 2) <= 1.0) 
         idaire += 1; 
       } 
       pi = 4 * (double)idaire/(double)nmax; 
       nmax *= 10; 

       list1.Items.Add(
        "Iterasyon:" + 
        nmax.ToString() + 
        " ----->" + 
        pi.ToString() + 
        "\n"); 
       System.Threading.Thread.Sleep(100); 
      } 
      SimulationFrameWork.MCSDirector run = new SimulationFrameWork.MCSDirector(); 
      run.Update(id, pi); 
      list1.Items.Add("\n\n islem bitti..."); 
     } 
    } 
} 
+0

また、あなたの問題で、このソリューションをチェックアウト。非常にエレガントなものです:http://stackoverflow.com/questions/906057/problem-with-delegate-syntax-in-c/906097#906097 –

答えて

10

はちょうど別の方法をリストボックスにテキストを追加するカプセル化:

private void timer1_Tick(object sender, EventArgs e) 
{ 
    // ... 
    AddTextToListBox("\n\n işlem bitti..."); 
} 

private void AddTextToListBox(string text) 
{ 
    if(list1.InvokeRequired) 
    { 
     list1.Invoke(new MethodInvoker(AddTextToListBox), new object[] { text }); 
     return; 
    } 

    list1.Items.Add(text); 
} 
+4

このリンクに従ってください:http://msdn.microsoft.com/en-us/library/system.windows.forms.methodinvoker.aspx .NETでパラメータを持つメソッドを持つMethodInvokerデリゲートを使用する4.この質問に対する答えを探している場合は、以下のOneSHOTのソリューションを確認してください。 –

15

これは、その周りに

private delegate void stringDelegate(string s); 
private void AddItem(string s) 
{ 
    if (list1.InvokeRequired) 
    { 
     stringDelegate sd = new stringDelegate(AddItem); 
     this.Invoke(sd, new object[] { s }); 
    } 
    else 
    { 
     list1.Items.Add(s); 
    } 
} 

をあなたを取得する必要がありますだけで、それ以外の場合は、単に追加されますAddItemメソッドを呼び出し、それが必要な場合は、このデリゲートを使用してアドオンを起動します項目を直接ボックスに追加します。

ワンショット

+0

あなたのコードにも気がついた " 0; i "+ pi.ToString()+" \ n ");直後(int i = 0; i – OneSHOT

+2

)余分なデリゲートを宣言する必要はありません; MethodInvokerを使用してこれを行うことができます。 –

+0

DoWork、ProgressChanged、RunWorkerCompleted – Penguen

-4

は、スレッドを開始する前にこのコードを追加します。

//kolay gelsin kardeş) 
CheckForIllegalCrossThreadCalls = false; 
thread1.Start(); 
+3

これは良い考えではありません。予期せぬ壮大な誤りと引き換えに、 –

0

もラムダ表記を使用することができます。だから、代わりに:

formControl.Field = newValue; //Causes error 

試してみてください。

Invoke(new Action(() => 
{ 
    formControl.Field = newValue; //No error 
})); 
関連する問題

 関連する問題