1

Есть форма, которая открыта в основном потоке.

В ней вызывается другая форма, но она открывается в новом потоке.

Из этой новой формы вызывается метод другого класса, который изменяет содержимое RichTextBox той форме, в которой вызывался метод.

Ошибка: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'richTextBox1' не из того потока, в котором он был создан."

Вот код функции, которая изменяет содержимое RichTextBox:

public void writeLog(string word, RichTextBox logBox)
{
        logBox.SelectionStart = logBox.TextLength;
        logBox.SelectionLength = 0;
        logBox.SelectionColor = Color.YellowGreen;
        logBox.AppendText(Environment.NewLine + voids.GetTimeNow());
        logBox.SelectionColor = logBox.ForeColor;
        logBox.AppendText(word);
        logBox.SelectionStart = logBox.Text.Length;
        logBox.ScrollToCaret();
}

Вот вызов той функции:

private Voids voids = Voids.GetInstance();
voids.writeLog("Какой то текст", richTextBox1);

А вот так открывается форма в новом потоке:

private void button1_Click(object sender, EventArgs e)
{
            new System.Threading.Thread(() =>
            {
                NewForm();
            }).Start();
}
void NewForm()
{
            Form1 form = new Form1();
            form.ShowDialog();
}
Behavior
  • 149
  • А какой вопрос отмечен как источник для дубликата? – VladD Aug 08 '17 at 17:32
  • @VladD вот этот: https://ru.stackoverflow.com/questions/418461/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B0%D0%BC%D0%B8-%D0%B8%D0%B7-%D1%84%D0%BE%D0%BD%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0 – Behavior Aug 08 '17 at 17:34
  • 2
    Ну всё правильно, дубликат. Вам нужно переброситься в исходный поток. Async/await не подойдёт, т. к. вы стартуете не в том контексте, а BeginInvoke самое оно. – VladD Aug 08 '17 at 17:37
  • @VladD, BeginInvoke на чём? Он же создаёт новую форму. Что-то мне кажется, тут другая проблема. – Qwertiy Aug 08 '17 at 17:41
  • @Qwertiy: Ну он хочет из второго UI-потока доступиться к первому. «Из этой новой формы вызывается метод другого класса, который изменяет содержимое RichTextBox той форме, в которой вызывался метод.» Соответственно нужно писать ричТекстБоксМоейБабушкиОдин.БегинИнвоке(...). – VladD Aug 08 '17 at 17:42
  • @VladD, погоди. А new Form из другого потока - это точно нормально? И ShowDialog относительно чего её модальной будет делать? – Qwertiy Aug 08 '17 at 17:46
  • @Qwertiy: Ну вроде норм, ShowDialog запускает собственный цикл сообщений. Ну а модальной относительно ничего, думаю :) – VladD Aug 08 '17 at 18:14
  • @Behavior перечитайте ответ по ссылке, попробуйте применить его к своему коду. Если результат не заработает, или что-то не получится - отредактируйте вопрос и приведите новый код - его переоткроют и кто-нибудь вам ответит. –  Aug 12 '17 at 20:25

1 Answers1

0

Дело в том, что доступ к элементам управления может осуществляться только из потока, в котором он был создан. Если вы хотите получить доступ к элементу управления из другого потока, то можете использовать пару методов BeginInvoke и EndInvoke, здесь можно почитать об этом здесь можно почитать об этом

Также вы можете использовать паттерн async/await.

И еще, лучше используйте объекты System.Threading.Tasks.Task для выполнения задач из другого потока, это позволит CLR более правильно управлять потоками.

Andrei S.
  • 489
  • 1
    Топикастеру уже дали такой же (и даже более подробный) ответ , в виде отметки дубликата https://ru.stackoverflow.com/questions/418461/ –  Aug 12 '17 at 20:20
  • @PashaPash разве можно дать ответ на вопрос уже отмеченный дубликатом? –  Aug 13 '17 at 06:42
  • @FoggyFinder нет, но топикастер удалил свой ответ и запостил его заново (без изменений). Ему об этом явно написали в комментариях, вопросы слили - но на "новый" вопрос успели ответить в стиле "здесь можно почитать об этом" :( –  Aug 13 '17 at 08:43
  • @FoggyFinder кстати, Delgate.BeginInvoke/EndInvoke, на который сослался автор ответа, не имеют никакого отношения к Control.BeginInvoke, которым решается проблема из вопроса :). Как и упомянутые Task - они тоже ничем топикастеру не помогут. –  Aug 13 '17 at 08:48
  • @PashaPash Во-первых, Delegate.BeginInvoke или Control.BeginInvoke это не столь принципиально, я просто дал направление автору вопроса. Во-вторых, async/await автору могут помочь в этом вопросе - по сути трушный async/await завязан на EAP. – Andrei S. Aug 13 '17 at 09:14
  • 1
    @AndreiS.в каком смысле "не столь принципиально"? Там из общего - только название метода. Статья по ссылке не имеет никакого отношения к вопросу. Т.е. направление вы дали, но это направление вникуда :)). Да, вы упомянули async/await. Но вы читали вопрос/ответ, на который завернули вопрос автора? Как вы думаете, в том ответе упомянуты Control.BeginInvoke и async/await? –  Aug 13 '17 at 09:21
  • @AndreiS.т.е. не подумайте что я ворчу, но в вашем ответе отношение к вопросу имеет только "вы можете использовать паттерн async/await". А это тянет максимум на комментарий. Т.е. вы вообще ни в чем не виноваты - просто автор вопроса решил не читать ссылку на дубликат в своем первом вопросе, и просто запостил его второй раз. Но тем не менее - стоит обращать внимание на комменты под вопросом, особенно если там есть упоминание дубликата - на многие стандартные вопросы на сайте уже есть развернутые ответы. –  Aug 13 '17 at 09:28
  • @PashaPash Тот вопрос, на который завернули поставлен четко, поэтому на него можно дать четкий ответ, здесь же не совсем понятно, что у автора вообще происходит, ясно только, что где-то он допускает обращение к контролу для изменения из другого потока. И да, я посмотрел вопрос, на который завернули текущий, и, разумеется там упоминается и async/await и Begin/EndInvoke. Да, я пропустил этот комментарий, и я хотел оставить свой ответ в виде комментария, но на тот момент у меня еще не было достаточно очков репутации для этого. Я согласен, что на полноценный ответ это конечно не тянет :) – Andrei S. Aug 13 '17 at 09:30
  • @AndreiS.если у автора непонятно что происходит - ставьте на вопрос тревогу соответствующего типа - вопрос закроют пока автор не принесет достаточно кода для воспроизведения –  Aug 13 '17 at 09:33