class COMPortThread
{
// Очередь с данными для COM порта
// COMData - класс, хранящий данные для передачи в COM порт
// (по сути - сообщение COM порту)
private Queue<COMData> dataQueue;
// Событие, сигнализирующее о доступности данных в очереди
private ManualResetEvent dataAvailable;
//...
// Этот метод является основным методом потока
private void ThreadProc()
{
// Цикл посылки данных
// (на самом деле он, естественно, должен быть не бесконечным)
while(true)
{
// Ожидаем поступления данных в очередь
dataAvailable.WaitOne();
// Получаем очередные данные
COMData data = GetData();
// Здесь посылаем данные в COM порт
// и выполняем другие необходимые действия
// ...
}
}
private COMData GetData()
{
COMData result;
lock(dataQueue)
{
// Получаем очередные данные
result = dataQueue.Dequeue();
// Если очередь пуста - сбрасываем событие доступности данных
if(dataQueue.Count == 0) dataAvailable.Reset();
}
return result;
}
// Метод посылки данных из других потоков
public void Send(COMData data)
{
lock(dataQueue)
{
// Помещаем данные в очередь
dataQueue.Enqueue(data);
// Устанавливаем событие доступности данных
dataAvailable.Set();
}
}
}
Аналог очереди сообщений в потоке
В C++ я создаю поток. в этом потоке - очередь сообщений. При необходимости что-нибудь сделать, в эту очередь помещается сообщение. Сообщения выполняются ПОСЛЕДОВАТЕЛЬНО, причём вызывающие потоки не останавливаются. Все счастливы, все довольны :)
Как реализовать подобное на C#? Т.е. есть ли возможность посылать сообщения в поток?
И ещё вопрос. Если два метода одного объекта вызываются через BeginInvoke, то гарантируется ли то, что они выполнятся ПОСЛЕДОВАТЕЛЬНО?
ps. У меня проблемы с синхронизацией :( Система сама создаёт поток для формы и поток для COM-порта. Получается что связывающий объект (который обрабатывает данные от формы и от порта) работает в двух потоках одновременно :(. Отсюда и проблемы.
Два метода, вызванные асинхронно пр помощи BeginInvoke завершаться по разному вне зависимости от того, кто первый был запущен. Для того, чтобы доджаться завершения метода, вызовите EndInvoke, что вызовет синхронизацию. И объекты UI и объект SerialPort выполняются в одном потоке. Просто события, возникающие в интерфейсе и COM-порте асинхронны. Потоки умеют общаться через методы Thread.Pulse и Thread.PulseAll. Есть конечно структура System.Windows.Forms.Message, которая предоставляет функционал Windows-сообщения.
По поводу BeginInvoke. Просто есть много методов. Они никак не взаимосвязаны, но вызываются из разных потоков. Нужно, чтобы все они выполнялись в одном потоке.
Т.е. грубо говоря. Пусть два потока хотят одновременно записать данные в порт. Последовательность этих действий не важна. Важно только, чтобы пока идёт запись данных первого потока, данные второго потока ожидали "своей очереди".
Пример не очень удачный. На самом деле всё намного сложнее. Но надеюсь, что это пример передал суть вопроса:)
Код:
Чтобы послать данные из другого потока просто вызывается метод Send. Если данных нет, то поток простаивает в ожидании установки события dataAvailable. В коде опущено создание и завершение потока, но думаю, это не представляет сложности.