2009-05-29 62 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 – 2009-05-29 09:10:07

回答

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); 
} 
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和使用委託,如果它是必需的,否則它只會增加,這將調用Add該項目直接到框。

ONESHOT

+0

只是注意到你的代碼也有一個迷路「在線(int i = 0; i「+ pi.ToString()+」\ n「);我只需要(int i = 0; i – OneSHOT 2009-05-29 08:58:05

+2

)聲明額外的代表是不必要的;您可以使用MethodInvoker來執行此操作... – 2009-05-29 09:05:35

+0

是否有任何方法簡單的方法:DoWork,ProgressChanged,RunWorkerCompleted – Penguen 2009-05-29 09:10:40

-4

啓動線程之前添加以下代碼:

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

也可以用拉姆達符號。因此,而不是:

formControl.Field = newValue; //Causes error 

嘗試:

Invoke(new Action(() => 
{ 
    formControl.Field = newValue; //No error 
})); 
相關問題