Laden...

Dispatcher bricht einfach ab

Erstellt von Big Al vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.208 Views
B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 13 Jahren
Dispatcher bricht einfach ab

Hallo,
ich habe eine ThreadSafeObservableCollection ähnlich dieser hier: http://blogs.microsoft.co.il/blogs/tamir/archive/2007/04/22/Thread-safe-observable-collection.aspx
Bei der InsertItem Methode scheint es aber ein Problem zu geben, denn diese Zeile:

dispatcher.Invoke(DispatcherPriority.DataBind, (SendOrPostCallback)delegate { InsertItemImpl(args); }, args);

bricht einfach ab und führt den Aufruf

InsertItemImpl(args);

gar nicht mehr aus. Da ich mich mit dem Dispatcher nicht übermäßig gut auskenne, würde es mich freuen, wenn mir jemand erklären könnte, woran das liegt. Vielleicht falsche Parameter? Hier noch einmal der Code für InsertItem und InsertItemImpl:


protected override void InsertItem(int index, T item)
        {
            if (dispatcher.CheckAccess())
            {
                if (index > this.Count)
                    return;
                LockCookie lock_cookie = rw_lock.UpgradeToWriterLock(-1);
                base.InsertItem(index, item);
                rw_lock.DowngradeFromWriterLock(ref lock_cookie);
            }
            else
            {
                object[] args = new object[] { index, item };
                dispatcher.Invoke(DispatcherPriority.DataBind, (SendOrPostCallback)delegate { InsertItemImpl(args); }, args);//Hier wird abgebrochen
            }
        }

        void InsertItemImpl(object[] args)
        {
            if (dispatcher.CheckAccess())
            {
                InsertItem((int)args[0], (T)args[1]);
            }
            else
            {
                dispatcher.Invoke(DispatcherPriority.DataBind, (SendOrPostCallback)delegate { InsertItemImpl(args); }, null);
            }

        }

Vielen Dank,
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Big Al,

in welchem Kontext benutzt du die Klasse? In eine Konsolenanwendung oder in einer Forms oder WPF Anwendung?

Und in welchem Thread wird die Collection erzeugt?

... bricht einfach ab und führt den Aufruf ... gar nicht mehr aus

Woher weißt du das? Vermutlich wird die Methode nur in einem anderen Thread ausgeführt.

Davon abgesehen ist die Implementierung unnötig kompliziert. Auf InsertItemImpl kann man ganz verzichten und stattdessen in Dispatcher.Invoke gleich InsertItem aufrufen. Warum das der Blog-Autor nicht macht, obwohl er schreibt "You can not implement your delegate with parameter and without return value better", also weiß, dass man beliebige Parameter übergeben kann und das object[] also gar nicht braucht, ist mir schleierhaft. Und selbst wenn man InsertItemImpl unbedingt haben wollte, ist es Quatsch darin CheckAccess abzufragen, weil das sowieso immer true ist, weil InsertItemImpl ja immer per Dispatcher.Invoke aufgerufen wird.

Ein bisschen fragwürdig ist auch, dass in InsertItem noch per ReaderWriterLock synchronisiert wird, obwohl alle Zugriffe auf die innere Collection in dem angedachten Kontext sowieso nur aus einem einzigen Thread heraus durchgeführt werden. In dem angedachten Kontext können also überhaupt keine gleichzeitigen Zugriffe stattfinden.

herbivore

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 13 Jahren

Hallo Herbivore,
ich benutze das ganze in einer WPF Anwendung, in der im Hintergrund Daten geladen werden. Hier soll dann auch die ThreadSafeObservableCollection gefüllt werden. Wenn währenddessen die GUI die Collection über DataBinding beansprucht, muss das ganze ja synchronisiert werden. Ein bisschen stutzig war ich bei der Klasse auch, ich musste schon eine "Parameter count mismatch" Exception beheben und das viele CheckAccess kam mir auch seltsam vor. Ich habe noch eine Implementierung bei CodeProject gefunden. Die benutzt Lambda-Ausdrücke statt der anonymen Methoden.
Dass die Methode InsertItemImpl nicht aufgerufen wird habe ich daraus geschlossen, dass ein Breakpoint darin nicht die Ausführung gestoppt hat. Außerdem war das "geinsertete" Item nach dem Aufruf von InsertItem nicht in der Collection.
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Big Al,

Ich habe noch eine Implementierung bei CodeProject gefunden.

und mit der funktioniert es?

herbivore

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 13 Jahren

Hallo Herbivore,
mit der CP Version hab ich es noch nicht probiert, ich werde meine Erfahrungen hier posten.
Grüße,
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 13 Jahren

Hi,
das funktioniert auch nicht, da muss es wohl am Code drumherum liegen. Ich lade im Hintergrund Informationen, die in eine Collection kommen. Ein ViewModel greift dann, wenn der Ladevorgang abgeschlossen ist, auf die Collection zu und erstellt ViewModels der geladenen Items und schreibt sie in eine eigene ObservableCollection.
Hier mal ein bisschen Code der Methode, die nach dem Laden aufgerufen wird:


protected override void OnInformationLoadingCompleted(IAsyncResult res)
        {
            (res.AsyncState as Action).EndInvoke(res);

            //Hier kommt der Teil, der abschmiert:
            foreach (Appeal.Model.Base.Comment c in ((OnlineApp)Model).GetComments())
            {
                CommentViewModel vm = new CommentViewModel(c);
                Comments.Add(vm);
            }

            infoLoaded = true;
       }

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 13 Jahren

Hallo,
ich habe das Problem gelöst. Es lag daran, dass der Dispatcher auch in einem anderen Thread als dem GUI Thread erzeugt wurde. Da liefert Dispatcher.CurrentDispatcher natürliche einen falschen.
Vielen Dank für die Hilfe,
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Big Al,

das mit dem richtigen Thread wollte ich gerade als Aussage schreiben, da bist du mir zuvorgekommen. Als Frage hatte ich das Thema ja schon angerissen:

Und in welchem Thread wird die Collection erzeugt?

Wobei das immer noch nicht erklärt, warum das Element nicht in der Collection gelandet ist. Denn ein falscher Dispatcher sollte ja nur dazu führen, dass der Code im falschen Thread ausgeführt wird, nicht dass er gar nicht ausgeführt wird.

herbivore