#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 продолжает опрашивать