Zmiana wartości UI z innego wątku

0

Witam!

Mam mały problem, a mianowicie mam za zadanie zrobić ekran startowy, do którego co jakiś czas będzie wysyłana informacja z głównej aplikacji co aktualnie się ładuje i ma się to pojawić na tymże ekranie, jednak mam problem z działaniem na wątkach, uproszczony, podglądowy kod:

class Background{
	BitmapImage Image
	int height;
	int Width;
}
class Font{
	//fields
}

class Element{
	Font font;
	Point position;
	string diplayText;
}

class Data{ //ViewModel
	public ObservableCollection<Element> Elements {get;set;}
	public Background BackgroundImg {get;set;}
	public Element Message {get;set;}

	AddElement(Element e){
		Elements.Add(e);
	}
}

class Creator{

	Instance; //Singleton
	XDocument document1;
	XDocument document2;

	void LoadDocuments();
	void SetElements();
	void SetMessage(string message);
        Element CreateElement();

	void Show(){
		Thread thread = new Thread(ShowWindow);
		thread.ApartmentState = ApartmentState.STA;
		thread.Start();
	}
}

Kilka słów wyjaśnienia: Na ekranie jest kilka innych elementów, które są ustaawiane raz na samym początku (ObservableList) i jeden element z wiadomością do wyświetlania. Mój problem polega na tym, że aplikacja wysypuje się, wtedy, gdy chcę dodać Elementy do tablicy z innej metody niż Show(); i dodać/zmienić wiadomość. Wiem czemu tak się dzieje, ale nie mam pojęcia jak mogę temu zapobiec. Próbowałem działać z dispatcherem, ale niestety nic nie działa. Zależy mi na tym, żeby wywołanie SetMessage() działało z dowolnego miejsca, ale nie mam pojęcia jak to osiągnąć.

1
  1. ten „uproszczony, podglądowy” kod składa się prawie w całości z rzeczy nie związanych z problemem. Nie widać w nim nawet czego używasz do GUI.
  2. „nie da się” zmienić stanu kontrolki z innego wątku. po to jest Invoke i Dispatcher żeby wykonać fragment kodu w wątku głównym (który to wątek główny cyklicznie sprawdza czy nie ma tego typu rzeczy do wykonania, oczywiście pod warunkiem że wątek ten nie wisi na czymś innym…)

Próbowałem działać z dispatcherem, ale niestety nic nie działa.

Co to znaczy nie działa.

0

Wygląda to tak: mam aplikację, która korzysta z kodu, który znajduje się w dllce, ładuje pliki konfiguracyjne i okresowo wysyła do okna informację z nową wiadomością do wyświetlenia, czyli z punktu widzenia aplikacji wygląda to tak:

Creator creator = new Creator();
LoadDocuments();
SetElements();
//jakiś kod ładujący
SetMessage(wiadomość1);
//jakiś kod ładujęcy
SetMessage(wiadomość2);
//I tak dalej
Close();

Więc główny wątek ładuje dane a okno jestna nowym wątku.
Do okna GUI podpięta jest klasa "Data" jako ViewModel.

0

Ciągle nie wstawiłeś kompletnego kodu który pozwala zreprodukować Twój problem, także strzelam, jeśli używasz WPF 4.5 to możesz spróbować wstawić do klasy Data następujący fragment kodu:

private static object lockOnElements  = new object();


Data()
{ 
    // w konstruktorze zaraz po tym jak utworzysz kolekcję Elements 
    BindingOperations.EnableCollectionSynchronization(Elements , lockOnElements  );
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1