Zmiana wartości UI z innego wątku

Odpowiedz Nowy wątek
2018-02-20 20:46
inny007
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ąć.

Pozostało 580 znaków

2018-02-20 22:10
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.

Pozostało 580 znaków

2018-02-20 22:27
inny007
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.

Pozostało 580 znaków

2018-02-21 08:27
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  );
}

Java to taki C# tyle że z gorszą składnią.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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