Отвечая на мой собственный вопрос, вот лучшее решение, которое я нашел до сих пор. Классы A и B (которые представляют элементы GUI) наследуются от класса Base, который содержит статический указатель на объект parent . Один и тот же родительский объект предоставляет друзьям доступ к A и B, чтобы они могли обращаться к открытым функциям друг друга по мере необходимости. Преимущество этой системы в том, что вы можете очень легко создавать и связывать новые объекты GUI (C, D ...): все, что вам нужно, это наследовать от Base и обновлять дружбу в Parent.
Вот код:
class Parent; // forward declaration for Base class static variable
class Base // class Base is just there to hold a pointer to the parent object for its derived classes
{
private:
static Parent * parent_ptr;
public:
Parent* getParent() const { return parent_ptr; }
};
class A : public Base
{
public:
int a_int;
A(const int a) : a_int(a) {}
void someFunction() const { std::cout << a_int; }
};
class B : public Base
{
public:
int b_int;
B(const int b) : b_int(b) { doSomethingToA(); } // Initiating this from the constructor, but really I would want to wait for a Listener
void doSomethingToA() const;
};
class Parent
{
private:
A a = { 2 };
B b = { 3 };
friend class A;
friend class B;
} parent;
Parent* Base::parent_ptr = &parent;
void B::doSomethingToA() const { getParent()->a.someFunction(); }
Используя ссылку, предоставленную Кентом, Вы могли использовать следующий код для изменения набора через потоки:
while (!Monitor.TryEnter(_lock, 10))
{
DoEvents();
}
try
{
//modify collection
}
finally
{
Monitor.Exit(_lock);
}
Если однако Вы просто надеетесь изменять набор на своем исходном потоке, можно попытаться использовать обратный вызов для потока UI. Я обычно делаю что-то вроде этого:
this.Dispatcher.Invoke(new MyDelegate((myParam) =>
{
this.MyCollection.Add(myParam);
}), state);
Вы в основном добрались для Вызова или BeginInvoke к потоку UI, чтобы сделать те операции.
Public Delegate Sub AddItemDelegate(ByVal item As T)
Public Sub AddItem(ByVal item As T)
If Application.Current.Dispatcher.CheckAccess() Then
Me.Add(item)
Else
Application.Current.Dispatcher.Invoke(Threading.DispatcherPriority.Normal, New AddItemDelegate(AddressOf AddItem), item)
End If
End Sub