1

Как запустить метод с UI потока? У меня есть статичный класс Log для вывода сообщений в лог со всех частей программы. Выглядит так:

static class Log
{
    static private ListBox _loglistbox;
    public static void initialize(ListBox loglistbox)
    {
        _loglistbox = loglistbox;
    }
    public static void addComment(string comment)
    {
        _loglistbox.Items.Add(comment);
        _loglistbox.SelectedIndex = _loglistbox.Items.Count - 1;
        _loglistbox.SelectedIndex = -1;
    }
}

При старте я передаю туда в какой listbox писать и он исправно выполняет обязанности. Начал переводить свой основной метод в поток, чтобы не тормозил интерфейс при выполнении. С потока когда обращаюсь к классу Log получаю ошибку обращения с другого потока, подскажите пожалуйста, как правильно обратиться с другого потока к классу Log, чтобы он смогу вывести сообщение в listbox?

        private void button2_Click(object sender, EventArgs e)
    {
        Thread writeDataThread = new Thread(writeDataToBase);            
        writeDataThread.Start(); 
    }            
        private void writeDataToBase()
    {
        Log.addComment("Start"); // ошибка
    }

2 Answers2

2
public static void addComment(string comment)
{
    _loglistbox.Dispatcher.BeginInvoke(new Action(() => 
    {
        _loglistbox.Items.Add(comment);
        _loglistbox.SelectedIndex = _loglistbox.Items.Count - 1;
        _loglistbox.SelectedIndex = -1; 
    }));
}
yolosora
  • 4,217
  • А где обращение к статическому классу?Как оно будет работать? – Roman Ieromenko Mar 20 '18 at 13:48
  • 1
    @RomanIeromenko не понял вопроса... К какому статическому классу и зачем? – yolosora Mar 20 '18 at 13:49
  • @RomanIeromenko это валидное решение для WPF (там у всех контролов есть свойство Dispatcher). У вас - решение для Winforms. –  Mar 20 '18 at 15:49
  • Спасибо, буду знать – Roman Ieromenko Mar 20 '18 at 15:51
1

У меня другое решение без класса закрытого Dispatcher, во-первых я бы добавил свойство для _loglistbox:

 static class Log
{
    static private ListBox _loglistbox;
    **static public ListBox Loglistbox { get { return _loglistbox; } }**
    public static void initialize(ListBox loglistbox)
    {
        _loglistbox = loglistbox;
    }
    public static void addComment(string comment)
    {
        _loglistbox.Items.Add(comment);
        _loglistbox.SelectedIndex = _loglistbox.Items.Count - 1;
        _loglistbox.SelectedIndex = -1;
    }       
}

Ну а сама реализация такова, кстати упустили, откуда берется внутренняя статическая переменная класса ListBox

 private void writeDataToBase()
    {                      
        BeginInvoke((MethodInvoker)
                    (() =>
                    {
                        **Log.initialize(new ListBox());**
                        Log.addComment("Bla Bla Bla");
                    }
                    ));
    }
  • Спасибо за помощь, решил подобным образом:if (_loglistbox.InvokeRequired) _loglistbox.Invoke(new Action<string>((s) => { _loglistbox.Items.Add(s); }), comment); – viton-zizu Mar 21 '18 at 13:13