Одна вещь, которая действительно хороша в программировании GUI, это то, что вам не нужно беспокоиться о том, что несколько потоков могут испортить вам жизнь (при условии, что у вас есть CheckForIllegalCrossThreadCalls = true
, как и должно быть). Это все однопоточные, работающие с помощью насоса сообщений (очереди), который обрабатывает входящие сообщения по одному.
Поскольку вы указали, что вам нужно синхронизировать вызовы методов, которые не написаны как поточно-ориентированные (полностью понятные), нет никаких причин, по которым вы не можете реализовать свой собственный обработчик сообщений для обработки ваш ультразвуковой объект.
Наивная, очень упрощенная версия может выглядеть примерно так (класс BlockingCollection<T>
отлично подходит, если вы используете .NET 4.0 или установили Rx-расширения ; в противном случае, Вы можете просто использовать простую ваниль Queue<T>
и сделать свою собственную блокировку). Предупреждение : это просто быстрый скелет, который я сейчас собрал; Я не даю никаких обещаний относительно его прочности или даже правильности.
class MessagePump<T>
{
// In your case you would set this to your Ultrasound object.
// You could just as easily design this class to be "object-agnostic";
// but I think that coupling an instance to a specific object makes it clearer
// what the purpose of the MessagePump<T> is.
private T _obj;
private BlockingCollection<Action<T>> _workItems;
private Thread _thread;
public MessagePump(T obj)
{
_obj = obj;
// Note: the default underlying data store for a BlockingCollection<T>
// is a FIFO ConcurrentQueue<T>, which is what we want.
_workItems = new BlockingCollection<Action<T>>();
_thread = new Thread(ProcessQueue);
_thread.IsBackground = true;
_thread.Start();
}
public void Submit(Action<T> workItem)
{
_workItems.Add(workItem);
}
private void ProcessQueue()
{
for (;;)
{
Action<T> workItem = _workItems.Take();
try
{
workItem(_obj);
}
catch
{
// Put in some exception handling mechanism so that
// this thread is always running. One idea would be to
// raise an event containing the Exception object on a
// threadpool thread. You definitely don't want to raise
// the event from THIS thread, though, since then you
// could hit ANOTHER exception, which would defeat the
// purpose of this catch block.
}
}
}
}
Тогда произойдет следующее: каждый раз, когда вы хотите каким-либо образом взаимодействовать с вашим ультразвуковым объектом, вы делаете это через этот насос сообщений, вызывая Submit
и выполняя какое-то действие, которое работает с вашим ультразвуковым объектом. Затем объект ультразвука получает все сообщения, отправленные ему синхронно (я имею в виду, по одному за раз), работая в своем собственном потоке без GUI.