Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Сокеты и многопоточность


Автор: 123456789igor 15.9.2014, 22:25
Здравствуйте. Есть у меня такая проблема. Никак не могу понять как организовать выполнение 2х различных задач параллельно. 
Есть клиент-серверное приложение. 1 метод отвечает за ожидание подключения и прием данных, 2ой метод отвечает за действия над принятыми данными.
Выглядит это так
Код

private async void Form1_Load(object sender, EventArgs e)
        {
            while (true)
            {
                new Thread(() => Run()).Start();
            }
            while (true)
            {
                if (massOfWords[0] != "")
                    break;
            }
            WorkWithDB db = new WorkWithDB();
            new Thread(() =>db.isLogonOrRegistration(massOfWords)).Start();

        }
public async Task Run()
        {
            massOfWords = await StartServer();
        }

public async Task<String[]> StartServer()
        {
            Socket _server;
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            //ServerSocket ss = new ServerSocket(ipAddress, 11000);
            _server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _server.Bind(new IPEndPoint(ipAddress, 11000));
            _server.Listen(20);
            ServerSocket ss = new ServerSocket();
            string result = await ss.Accept(_server);
            Console.WriteLine(result);
            _server.Close();
            _server.Dispose();
            return result.Split('|');
        } 


В результате хочу получить что-то вроде: запускаем приложение, метод Run запускается в новом потоке(выполнение программы идет дальше) программа крутится в цикле, пока какой-то клиент не подключится и не передаст данные. В случае если что-то получили запускаем метод isLogonOrRegistration в ещё 1ом потоке, при этом поток, в котором Run, работает и ждет следующего подключения. Никак не могу понять как это сделать
Если у вас есть идея как эту логику реализовать по другому- напишите пожалуйста. 
собственно сама логика: Этот кусок кода- это сервер. Клиент вводит креды и отправляет их серверу(сервер может обрабатывать подключения множества клиентов) далее сервер проверяет верные креды ли ввел пользователь. Никак не получается сделать это параллельно. Прошу совета.

Автор: Ilya81 17.9.2014, 14:10
Хоть с использованием оператора await я ещё не полностью освоился, но всё равно полагаю, что ожидающий поток - не самое подходящее для него применение. Рекомендую использовать EventWaitHandle с автоматическим сбросом. Т. е. ожидающий поток считывает все данные, после чего, пройдя цикл, останавливается на WaitOne. При чьём-то подключении вызывается метод Set и данные вновь считываются, затем поток вновь ждёт. Примерно так:
Код

        private volatile bool _isActive = true;
        private readonly EventWaitHandle _waitIncoming = new EventWaitHandle(false, EventResetMode.AutoReset);

        private void Loop()
        {
            while (_isActive)
            {
                ReadData();
                if (_isActive)
                    _waitIncoming.WaitOne();
            }
        }

Метод Loop выполняется в некотором потоке.

Автор: WERITAS 29.10.2014, 14:21
Класс EventWaitHandle используют пул потоков CLR,  а в нём их число ограниченно (по-моему 25). Поэтому если подключаться более 25-ти клиентов, то 26-му придётся ждать пока поток в пуле не освободится. Серверную часть приложения, работающего со множеством подключений, делают через Thread. А пул потоков используют для совершенно других задач по распараллеливанию!

Автор: Cheloveck 29.10.2014, 16:08
Как-то так...

Код

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleCs {
    public class Program {
        static ConcurrentBag<string> lines = new ConcurrentBag<string>();

        public static void Main(string[] args) {
            Listen();
            Console.Write("Press any key...");
            Console.ReadKey();
        }
        static void Listen() {
            while(true) {
                Console.Write("> ");
                string line = Console.ReadLine();
                if(String.Equals("q", line, StringComparison.InvariantCultureIgnoreCase)) {
                    PrintLines();
                    return;
                }
                HandleAsync(line);
            }
        }
        static void HandleAsync(string data) {
            new Task(() => {
                Thread.Sleep(2000); // Эмуляция бурной деятельности
                lines.Add(data);
            }).Start();
        }
        static void PrintLines() {
            Console.WriteLine("Entered strings:\n");
            foreach(string line in lines) {
                Console.WriteLine(line);
            }
        }
    }
}


Никаких асинков и эвейтов не надо тут, на вроде как.

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