Асинхронный процесс приводит к другому потоку

#c# #multithreading #asynchronous #windows-ce

#c# #многопоточность #асинхронный #windows-ce

Вопрос:

У меня есть приложение WinCE C #, которое опрашивает сервер (JAVA) на предмет асинхронных сообщений, поступающих. Чего я хочу добиться, так это того, что я хочу опросить сервер, и когда результат будет возвращен, поставить его в очередь, а затем обработать этот результат в другом потоке. Я хочу изолировать поток асинхронного приема от потока процесса, потому что после обработки ответа мне, возможно, придется отправлять дополнительные сообщения на сервер.

На данный момент у меня есть класс, аналогичный показанному здесь

http://msdn.microsoft.com/en-us/library/86wf6409(v=vs.80).aspx

для выполнения асинхронных запросов к серверу и чтения ответа. Я изменил класс, чтобы включить пользовательский тайм-аут, но это не должно иметь значения.

Что происходит в моем приложении, так это то, что я начинаю опрос в потоке ‘pollingThread’ и получаю ответ от сервера. В случае тайм-аута ответ будет нулевым, в противном случае я попытаюсь обработать ответ.

Я хочу отправить строку ответа другому потоку, который может работать над ее обработкой, в то время как мой pollingThread возвращается, чтобы продолжить опрос сервера. Я не могу понять, как получить ответ в другом потоке. Я знаю, как это сделать с помощью Monitor.Работает в больших окнах, но, к сожалению, он недоступен в NETCF 3.5.

Есть идеи?

Спасибо

РЕДАКТИРОВАТЬ: @Damon8or

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

AutoResetEvent _process объявлен статическим и виден для обоих методов

 ThreadStart processMethod= new ThreadStart(process);
processingThread= new Thread(processJSONMethod);
processingThread.IsBackground = true;
processingThread.Start();

ThreadStart startMethod = new ThreadStart(Poll);
connectionThread = new Thread(startMethod);
connectionThread.IsBackground = true;                    
connectionThread.Start();
  

внутри опроса у меня есть _process.Set() после получения строки с сервера. В методе process у меня есть:

 while (_keepPolling)
{

_process.WaitOne();

string text= MyQueue.Dequeue();
Debug.WriteLine("Returned: "   text

}    
  

И я не вижу печатаемой строки отладки. Метод опроса создает строку и помещает ее в очередь и возвращается к опросу.

Комментарии:

1. В чем именно заключается ваш вопрос?

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

Ответ №1:

Вы можете использовать либо AutoResetEvent, либо ManualResetEvent для подачи сигнала вашему рабочему потоку. Вот простой пример того, как.

     using System; 
    using System.Linq; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Threading; 

    namespace QueueDoodles 
    {
    class Program
    {
        public static readonly string[] data = { "a", "b", "c", "d", "e", "f", "g", "h" };

        static void Main(string[] args)
        {
            var running = true;
            var rand = new Random();
            var q = new Queue<string>();
            var qEvent = new ManualResetEvent(false);
            var pollThread = new Thread(new ThreadStart(delegate()
            {
                while (running)
                {
                    // Queue the next value
                    var value = data[rand.Next(data.Length)];
                    q.Enqueue(value);
                    Console.WriteLine("{0} queued {1}", Thread.CurrentThread.Name, value);

                    // Signal waiting thread
                    qEvent.Set();

                    // Simulate polling
                    Thread.Sleep(rand.Next(100));
                }
            }));
            pollThread.Name = "Poll Thread";

            var workerThread = new Thread(new ThreadStart(delegate()
            {
                while (running)
                {
                    // Wait on the queue
                    if (!qEvent.WaitOne())
                        break;
                    qEvent.Reset();

                    // Process the next queue item
                    var value = q.Dequeue();
                    Console.WriteLine("{0} queued {1}", Thread.CurrentThread.Name, value);
                }
            }));
            workerThread.Name = "Worker Thread";

            // Start the poll thread
            pollThread.Start();

            // Give it some time to fill queue
            Thread.Sleep(1000);

            // Start the worker thread
            workerThread.Start();

            // Wait for keyboard input
            Console.ReadLine();
            running = false;
            qEvent.Set();
        }
    }
}
  

Комментарии:

1. Пожалуйста, посмотрите на редактирование вопроса, я не смог вместить все это в комментарий. Спасибо

2. Я добавил поток. Sleep(10); сразу после set и, похоже, это помогло WaitOne() выйти из ожидания. Не уверен, что с этим делать, но теперь у меня есть другая проблема, когда два потока не работают параллельно. Поток обработки, похоже, блокирует connectionThread, хотя это не должно. Просто для проверки работоспособности у меня есть оба потока в качестве фоновых потоков. Имеет ли это значение? Спасибо

3. Я попытался переключиться на AutoResetEvent в моем коде QueueDoodle, и это сработало так же хорошо — прокомментировал вызов Reset(), поскольку это выполняется автоматически с этим типом. Должно быть что-то, что происходит с событием или вашим потоком обработки. Я широко использовал эти классы событий, и они всегда работают. Некоторые вещи, с которыми можно поэкспериментировать… -Добавьте отладочные состояния в свой поток обработки, чтобы увидеть, работает ли он вообще. -Добавьте время ожидания к WaitOne (1000) и проверьте возврат, просто чтобы увидеть, запускается ли событие. -Попробуйте ManualResetEvent, чтобы увидеть, ведет ли он себя по-другому.

4. Фон не должен иметь значения. Если thread.sleep (10) помог, это, вероятно, из-за вращения потока опроса или другого потока, который загружает процессор. Вам не нужен режим ожидания, если вы не хотите специально принудительно запускать другой поток в какой-то момент. Я удалил вызов sleep в своем примере, и он все еще работал нормально. Я знаю, что это не так уж полезно, но, возможно, исключите некоторые вещи из уравнения и просто сконцентрируйтесь на передаче сигналов потока, затем начните добавлять обработку и фактически опрашивать обратно в микс.

5. Да, поток. Режим ожидания (10) после Set() в Autoreset решил мою проблему. Я полагаю, что набор происходил в тот момент, когда никто не ждал, а затем, когда я перешел к ожиданию сразу после набора, мне нечего было извлекать. Спасибо за вашу помощь!

Ответ №2:

Класс queue потокобезопасен, почему бы не использовать queue для постановки ваших данных в очередь?

http://msdn.microsoft.com/en-us/library/system.collections .queue.aspx

Комментарии:

1. Кроме того, постановка данных в очередь — это не моя проблема. Я могу использовать для этого очереди. Моя проблема в том, как разбудить поток моего «процессора» для обработки результата, убедившись, что мой polingThread продолжает опрашивать