Как я могу исправить ошибку "доступ из потока, отличного от потока, в котором он был создан"? - PullRequest
7 голосов
/ 29 мая 2009

Этот следующий код дает мне ошибку ниже. Я думаю, что мне нужно "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...");
        }
    }
}

Ответы [ 4 ]

15 голосов
/ 29 мая 2009

Это должно вас обойти

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, и это вызовет добавление с использованием делегата, если это требуется, в противном случае он просто добавит элемент непосредственно в поле.

ONESHOT

10 голосов
/ 29 мая 2009

Просто инкапсулируйте добавление текста в список другим методом:

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);
}
0 голосов
/ 24 сентября 2014

Можно также использовать лямбда-нотацию. Итак, вместо:

formControl.Field = newValue; //Causes error

Попробуйте:

Invoke(new Action(() =>
{
    formControl.Field = newValue; //No error
}));
0 голосов
/ 19 октября 2010

Добавьте этот код перед запуском темы:

//kolay gelsin kardeş )
CheckForIllegalCrossThreadCalls = false;
thread1.Start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...