Делегаты в потоках и анонимных методах - Обновление элементов управления в новой теме - PullRequest
0 голосов
/ 18 января 2012

Я использовал многопоточность в моей форме окна.Следующий мой класс.В моем конструкторе есть элемент управления меткой, и в только что созданном потоке я обновляю его текстовое свойство.

Ниже приведен случай, когда я инкапсулировал функцию "UpdateLabel" в делегат "Del".и он отлично работает.

public partial class DynamicType : Form
    {
        delegate void Del(String x);

        public DynamicType()
        {
            InitializeComponent();
        }

        private void DynamicType_Load(object sender, EventArgs e)
        {
            System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(StartThread));
            t.Start();
        }

        private void StartThread()
        {
            this.Invoke(new Del(UpdateLabel), new object[] { "Hi" });
        }

        private void UpdateLabel(String str)
        {
            label1.Text = str;
        }
    }

У меня есть еще один случай, который называется Анонимные методы.При реализации анонимных методов в следующих методах.Ниже приведены определения.

private void StartThread()
        {
            UpdateLabel("Hi");
        }



private void UpdateLabel(String str)
        {
            Del Label = delegate(String k)
             {
                 label1.Text = k;

             };
            Label("hi");
        }

Недопустимая операция между потоками: доступ к элементу управления «label1» осуществляется из потока, отличного от потока, в котором он был создан.

Мой запрос выполнен в предыдущемВ этом случае я использовал делегатов, и это работало нормально, а в случае анонимных методов я удалил дополнительные функции, непосредственно создав их экземпляры, и попытался обновить свойство текста элемента управления label, и это вызвало сбой, как упомянуто выше.Причина

1 Ответ

1 голос
/ 25 января 2012

В первом примере вы вызываете обновление метки в потоке пользовательского интерфейса (через Form.Invoke). Это правильно и работает:

this.Invoke(new Del(UpdateLabel), new object[] { "Hi" });

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

Del Label = delegate(String k) { label1.Text = k; }; 
Label("hi");   // runs in the same thread

Чтобы решить эту проблему, вы должны использовать this.Invoke для выполнения делегата в потоке пользовательского интерфейса:

Del Label = delegate(String k) { label1.Text = k; }; 
this.Invoke(Label, new object[] {"hi"});   // runs in the UI thread
...