1

Нужно запустить N количество параллельных потоков и из них выводить данные в форму (ListBox) интерактивно. Вот приблизительно что получается:

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

    private string name;       
    private static List<string> listing = new List<string>();

    private void button1_Click(object sender, EventArgs e)
    {
        for (int i=1 ; i<5; i++)
        {
            name = i.ToString();
            Work w = new Work(name);
            Thread t = new Thread(new ThreadStart(w.DoWork));
            t.Start();
        }

    }

    class Work
    {
        private string m_name;
        public Work(string name)
        {                
            m_name = name;
        }
        public void DoWork()
        {
            for (int x = 0; x < 10; x++)
            {
                Form1.listing.Add(string.Format("Thread is working: {0} - Cycle: {1}", m_name, x));                    
                // Form1.list1.Items.Add(string.Format("Thread is working: {0} - Cycle: {1}", m_name, x));
            }
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        list1.DataSource = listing;
    }
}
Stack
  • 9,452
  • Если вам дан исчерпывающий ответ, отметьте его как верный (галка напротив выбранного ответа). – Nicolas Chabanovsky Jan 17 '16 at 08:14

1 Answers1

2

В ващем случае можно использовать метод Invoke. Он позволяет вызвать некоторый делегат из потока, связанного с указанным контролом (обычно с формой).

Но я советую использовать более современный способ:

private void button1_Click(object sender, EventArgs e)
{
    for (int i=1; i<5; i++)
        DoWork(i.ToString());
}

private async void DoWork(string name)
{
    for (int x = 0; x < 10; x++)
    {
        var y = await Task.Run(() => { return x; }); // Изображаем асинхронную работу в фоновом потоке

        list1.Items.Add(string.Format("Thread is working: {0} - Cycle: {1}", m_name, y));

        await Task.Delay(1000);
    }
}

Основной момент: цикл внутри DoWork "крутится" в основном потоке, а потому нет никаких проблем с доступом из него до компонентов формы. "Долгие" операции либо передаются в пул потоков (пример - "вычисление" переменной y) - либо же используется специальное асинхронное API, которое позволяет вообще не занимать поток (пример - Task.Delay).

С точки зрения вызывающей функции (button1_Click) функция DoWork возвращает управление как только в ней начнет выполняться первый из операторов await.

Pavel Mayorov
  • 58,537