Нужна помощь в получении информации через поток пользовательского интерфейса и другой поток в C #

StackOverflow https://stackoverflow.com/questions/229254

Вопрос

У меня есть серверное приложение, которое получает информацию по сети и обрабатывает ее. Сервер является многопоточным и обрабатывает несколько сокетов одновременно, а потоки создаются без моего контроля с помощью методов стиля BeginInvoke и EndInvoke, которые связаны соответствующими функциями обратного вызова.

Я пытаюсь создать форму, в дополнение к основному графическому интерфейсу, которая отображает элемент ListBox, заполненный элементами, описывающими подключенные в данный момент сокеты. Итак, в основном я пытаюсь добавить элемент в ListBox с помощью функции Add () из потока, в котором выполняется соответствующая функция обратного вызова. Я получаю доступ к своим элементам управления формами через свойство Controls - I.E:

(ListBox)c.Controls["listBox1"].Items.Add();

Естественно, я не просто вызываю функцию, я пробовал несколько способов, которые я нашел здесь и в Интернете, для связи между потоками, включая MethodInvoker , используя делегат , в сочетании с Invoke () , BeginInvoke () и т. д. Кажется, ничего не работает, я всегда получаю одно и то же исключение, сообщающее, что к моему элементу управления был получен доступ из потока, отличного от того, в котором он был создан.

Есть мысли?

Это было полезно?

Решение

Вы должны вызвать Invoke (или BeginInvoke) для элемента управления ListBox, к которому вы обращаетесь, для вызова делегата в потоке, создавшем этот элемент управления.

ListBox listBox = c.Controls["listBox1"] as ListBox;
if(listBox != null)
{
   listBox.Invoke(...);
}

Другие советы

Я всегда использовал что-то вроде этого:

        c = <your control>
        if (c.InvokeRequired)
        {
            c.BeginInvoke((MethodInvoker)delegate
            {
                //do something with c
            });
        }
        else
        {
            //do something with c
        }

Я также написал несколько вспомогательных методов расширения, чтобы ... помочь.

using System;
using System.ComponentModel;
public static class CrossThreadHelper
{
    public static bool CrossThread<T,R>(this ISynchronizeInvoke value, Action<T, R> action, T sender, R e)
    {
        if (value.InvokeRequired)
        {
            value.BeginInvoke(action, new object[] { sender, e });
        }

        return value.InvokeRequired;
    }
}

используется так:

     private void OnServerMessageReceived(object sender, ClientStateArgs e)
    {
        if (this.CrossThread((se, ev) => OnServerMessageReceived(se, ev), sender, e)) return;
        this.statusTextBox.Text += string.Format("Message Received From: {0}\r\n", e.ClientState);
    }

Использование BeginInvoke или Invoke должно работать нормально. Не могли бы вы опубликовать короткую, но полную программу, которая демонстрирует проблему? Вы должны быть в состоянии работать над тем, что на самом деле не требует каких-либо вещей на стороне сервера - просто есть куча потоков, которые "притворяются" получать входящие соединения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top