Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Асинхронный режим приема данных через сокет.


Автор: Хоббит 9.5.2006, 11:06
Конектюсь к серверу.
Как отправлят сообщения и как принимать разобрался. Но проблема в другом. При асинхроном принятии данных, фуннкция которая запускается для обработки - работает в другом потоке, нежели остальное приложение и следовательно не может получить прямо доступ к его  свойствам. То есть собщения я получаю, а вывести не могу.
Вот пример

Код

    public partial class IrcForm : Form
    {
        public IrcForm()
        {
            InitializeComponent();
        }

        private Socket socket;
        public Socket Socket
        {
            get
            {
                return socket;
            }
            set
            {
                socket = value;
            }
        }

        
        private void Connect(string Host, int Port)
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.BeginConnect(Host, Port, ReceiveData, this);                           
        }

        private void SendData(string Text)
        {
            socket.Send(Encoding.UTF8.GetBytes(Text));
        }

        private static void ReceiveData(IAsyncResult ar)
        {
            IrcForm ircForm = ar.AsyncState as IrcForm;
            Socket socet = ircForm.Socket;
            byte[] buffer = new byte[512];
            socet.Receive(buffer);
                        

            string text = Encoding.UTF8.GetString(buffer);
            ircForm.listChat.Items.Add(buffer);                                //Здесь  прога ругается.. типа ircForm.listChat находиться в другом потоке
        }

        private void IrcForm_Load(object sender, EventArgs e)
        {
            Connect("chat.tamboff.ru", 6670);
        }

    }

 

Автор: Хоббит 9.5.2006, 15:21
Проблема с приемом решается через свойство InvokeRequired  тект бокса

А вот как отправить... потому что данный вариант работает... сообщения через сокет на сервер льются.. а вот обратно никак ничего не приходит
 

Автор: mr.DUDA 10.5.2006, 11:36
Цитата(Хоббит @  9.5.2006,  14:21 Найти цитируемый пост)
А вот как отправить... потому что данный вариант работает... сообщения через сокет на сервер льются.. а вот обратно никак ничего не приходит
 

Проблема в том, что ответ вообще не приходит, или что в отдельном потоке ? Если про поток, то ты сам только что ответил: св-во InvokeRequired и метод Invoke в помощь. 

Автор: Хоббит 10.5.2006, 14:40
в том что вообще не приходит .... вот эта функция, кот в отдельном потоке ничего не принимает 

Автор: mr.DUDA 10.5.2006, 18:02
А у меня работает. То бишь данные приходят в буфер. 

Автор: Хоббит 10.5.2006, 22:21
а можно пример кодика? асинхронного.... я сделал синхронный прием.. проверяю наличие инфы каждую секунда и гружу если есть, все работает 

Автор: mr.DUDA 11.5.2006, 10:53
Твой пример - рабочий (за исключением записи в листбокс). С сокетами много не работал, а разбираться особо не хочется smile. 

Автор: Хоббит 11.5.2006, 11:10
... понял ... а не рабочесь примера в том, что он только  1 раз принимает данные асинхронно.. а потом замолкает 

Автор: mr.DUDA 11.5.2006, 12:57
Цитата(Хоббит @  11.5.2006,  10:10 Найти цитируемый пост)
... понял ... а не рабочесь примера в том, что он только  1 раз принимает данные асинхронно.. а потом замолкает  

Ну так ты ведь только 1 раз Connect вызываешь, не будет же он без конца ответы принимать smile
Или просто не все данные приходят ? Тогда нужно сделать цикл и вызывать socket.Receive до тех пор пока он не вернёт 0.

З.Ы. ещё не мешало бы в конце ReceiveData добавить вызов socket.EndRecieve(), может в этом проблема. 

Автор: albert21 13.5.2006, 22:47
Цитата

Проблема с приемом решается через свойство InvokeRequired  тект бокса


А можно поподробнее? У меня схожая проблема, не могу добраться до грида 

Автор: mr.DUDA 14.5.2006, 09:47
Цитата(albert21 @  13.5.2006,  21:47 Найти цитируемый пост)
А можно поподробнее? У меня схожая проблема, не могу добраться до грида 

объясняю подробнее:

1) работать с визуальными контролами и формами из нескольких потоков нельзя, валится исключение InvalidOperationException при попытке вызвать практически любой метод или свойство
2) поток, желающий что-либо сделать с контролом/формой, должен вызвать у контрола/формы метод Invoke, передав ему делегат на любой метод
3) контрол/форма вызовут метод по делегату, причём этот метод уже будет работать в "родном" потоке контрола/формы, что позволит данному методу безопасно работать со свойствами и методами контрола/формы

В двух словах, всё что нужно - это вызвать метод Invoke контрола (или формы) и передать ему делегат на метод, выполняющий всю работу.
  

Автор: ivashkanet 14.5.2006, 20:19
mr.DUDA, неразу такого не делал, но вопрос все же интересен  smile 
А как передеть значение из потока....
Писал, писал и подумал: "дай гляну на этот метод invoke", а там как раз все и написано:
Цитата
public object Invoke(Delegate method, params object[] args);
.
Только вот что получается. Если метод планируестся вызываться в invoke, то метод заранее должен уметь переконвертить из object в реальный тип, или это конвертирование проходит автоматически?
Опять поэкспериментировал и оказалось, что преобразование идет автоматом, хоть это радует  smile 
P.S. Еще замечание. Получается компилятор не может проверить соответствие типов smile 
Даже не смог проверить количество аргументов  smile 
Хм.. А зачем ему тогда нужено явно объявлять делегата  smile 
Наверное, invoke всетки хитрый метод. И именно он автоматом конвертирует типы и проверяет количество аргументов, на основании полученного делегата  smile 

Автор: mr.DUDA 14.5.2006, 22:50
ivashkanet, в Invoke можно передать делегат любого типа. Что мешает, например, передать делегат на метод, принимающий string или массив Rectangle-ов, или на Dictionary<string,int> и так даее ? В конце концов, можно объявить делегат с нужным набором аргументов. 

Автор: ivashkanet 15.5.2006, 08:09
Цитата(mr.DUDA @  14.5.2006,  22:50 Найти цитируемый пост)
ivashkanet, в Invoke можно передать делегат любого типа. Что мешает, например, передать делегат на метод, принимающий string или массив Rectangle-ов, или на Dictionary<string,int> и так даее ? В конце концов, можно объявить делегат с нужным набором аргументов. 

mr.DUDA, эт я понял  smile Даже написал:
Цитата(ivashkanet @  14.5.2006,  20:19 Найти цитируемый пост)
Наверное, invoke всетки хитрый метод. И именно он автоматом конвертирует типы и проверяет количество аргументов, на основании полученного делегата 

 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)