1

Только начал работать с потоками поэтому возникают тупые вопросы. Например я запускаю новый поток

new Thread(() => GetMessage(userId, false)).Start();

А в методе GetMessage() происходит присваивание текста контролеру RichTextBox. И во время такой операции вылетает Exception:

System.InvalidOperationException was unhandled Message=Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'exRichTextBox' не из того потока, в котором он был создан.
Source=System.Windows.Forms

Как это можно исправить?

Andriy Goliyad
  • 659
  • 6
  • 21

1 Answers1

5

Добавьте в свой проект след. класс:

using System;
using System.Windows.Forms;

namespace Tools
{
    public static class InvokeHelper
    {
        public static void SafeInvoke(this Control control, Action action)
        {
            if(control.InvokeRequired) {
                control.Invoke(action);
                return;
            }
            action();
        }

        public static void SafeInvoke(this Control control, Action action, T obj)
        {
            if(control.InvokeRequired) {
                control.Invoke(action, obj);
                return;
            }
            action(obj);
        }

        public static void SafeInvoke(this Control control, Action action, T1 obj1, T2 obj2, T3 obj3)
        {
            if(control.InvokeRequired) {
                control.Invoke(action, obj1, obj2, obj3);
                return;
            }
            action(obj1, obj2, obj3);
        }

        public static void SafeAsyncInvoke(this Control control, Action action)
        {
            if(control.InvokeRequired) {
                control.BeginInvoke(action);
                return;
            }
            action();
        }

        public static void SafeAsyncInvoke(this Control control, Action action, T obj)
        {
            if(control.InvokeRequired) {
                control.BeginInvoke(action, obj);
                return;
            }
            action(obj);
        }

        public static void SafeAsyncInvoke(this Control control, Action action, T1 obj1, T2 obj2)
        {
            if(control.InvokeRequired) {
                control.BeginInvoke(action, obj1, obj2);
                return;
            }
            action(obj1, obj2);
        }

        public static void SafeAsyncInvoke(this Control control, Action action, T1 obj1, T2 obj2, T3 obj3)
        {
            if(control.InvokeRequired) {
                control.BeginInvoke(action, obj1, obj2, obj3);
                return;
            }
            action(obj1, obj2, obj3);
        }
    }
}

А дальше в методе если опасаетесь, что он будет вызываться не из потока в котором создавался контрол (в принципе можно ставить во всех методах работающих с контролами формы в многопоточных приложениях):


private void SetText(string text)
{
    if(this.InvokeRequired) {
        this.SafeInvoke(SetText, text);
        return;
    }
    // . . .
    _richtextbox.Text = text;
}

Но помните, что внутри такого метода Вы уже работаете в потоке пользовательского интерфейса. Поэтому чтобы не было торможения UI не стоит в нем делать какие-либо продолжительные по времени действия.

Alexander
  • 322
  • 3
    Не стоит отвечать на явные дубликаты. Если хочется дать полезный ответ - дайте его в вопросе http://ru.stackoverflow.com/questions/418461/. Тем более что решение с Invoke/BeginInvoke уже давно устарело. –  Jul 28 '15 at 17:56