Задать вопрос

Доступ к контролу Windows Forms из другого потока (C#)?

Пробую писать программу, основной код которой будет выполняться в другом потоке и добавлять данные в ListBox по ходу работы.


Log — объект типа ListBox.


Создание потока:
private void bGo_Click(object sender, EventArgs e)
{
    ...
    Log.Items.Add("Старт");
    Thread t = new Thread(Download);
    t.Start();
    t.Join();
    ...
}



Работа потока:
void Download()
{
    for (int i = 0; i <= 2; i ++)
    {
        for (int j = 0; j <= 1000; j += 100)
        {
            Thread.Sleep(100);
            //реальный код слал запросы в сеть, 
            //т.е. большую часть времени простаивал
            WriteToLog("test");
        }
    }
}



Работа с ListBox'ом:
void WriteToLog(string message)
{
    if (Log.InvokeRequired)
    {
        Log.BeginInvoke(new Action<string>((s)
            => Log.Items.Add(s)), message);
    }
    else
    {
        Log.Items.Add(message);
    }
}



В результате выводится «Старт», затем трёхсекундная пауза и 30 «test», хотя всё это должно выводиться по ходу работы. Если заменить BeginInvoke на Invoke, программа зависает на этой строке на неопределённое время. Как сделать нормальный вывод?
  • Вопрос задан
  • 30592 просмотра
Подписаться 6 Оценить 2 комментария
Ответ пользователя Desiderata К ответам на вопрос (6)
Desiderata
@Desiderata
Попробуйте так:
delegate void WriteToLogDelegate(string message);
void WriteToLog(string message)
{
    if (Log.InvokeRequired)
    {
         var writeToLog = new WriteToLogDelegate(WriteToLog);
         Log.Invoke(writeToLog, message);
    }
    else
    {
        Log.Items.Add(message);
    }
}
Ответ написан