Vraag Moet afhankelijkheidsbron op dezelfde draad maken als het afhankelijkheidsobject


Ik bind waarneembaar woordenboek van te bekijken model om te bekijken. Ik gebruik Caliburn Micro Framework.

Uitzicht:

    <ListBox Name="Friends" 
             SelectedIndex="{Binding Path=SelectedFriendsIndex,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             SelectedItem="{Binding Path=SelectedFriend, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
             Style="{DynamicResource friendsListStyle}"
             IsTextSearchEnabled="True" TextSearch.TextPath="Value.Nick"
             Grid.Row="2" 
             Margin="4,4,4,4"
             PreviewMouseRightButtonUp="ListBox_PreviewMouseRightButtonUp"
             PreviewMouseRightButtonDown="ListBox_PreviewMouseRightButtonDown" 
             MouseRightButtonDown="ListBox_MouseRightButtonDown"
             Micro:Message.Attach="[MouseDoubleClick]=[Action OpenChatScreen()]" >

Code van weergave modelklasse.

Eigenschappen zien er als volgt uit:

public MyObservableDictionary<string, UserInfo> Friends
{
    get { return _friends; }
    set
    {
        _friends = value;
        NotifyOfPropertyChange(() => Friends);
    }
}

In Dispatcher-timer bel ik elke 3 seconden in aparte thread nieuwe servicemethode.

Dus ik constructor van view-model ik heb dit:

        _dispatcherTimer = new DispatcherTimer();
        _dispatcherTimer.Tick += DispatcherTimer_Tick;
        _dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
        _dispatcherTimer.Start();

        _threadDispatcher = Dispatcher.CurrentDispatcher;

En de tikmethode van Timer is hier:

    private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
    {
        new System.Threading.Tasks.Task(() =>
        {
            //get new data from server
            MyObservableDictionary<string, UserInfo> freshFriends = _service.GetFriends(Account);

            _threadDispatcher.BeginInvoke((System.Action)(() =>
            {
                //clear data, Friend is property which is binded on listobox control
                Friends.Clear();

                //here is problem - > refresh data
                foreach (var freshFriend in freshFriends)
                {
                    Friends.Add(freshFriend);

                }
            }));
        }).Start();

wanneer ik de app start, krijg ik de volgende foutmelding:

Must create DependencySource on same Thread as the DependencyObject.


   at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri)
   at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
   at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
   at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
   at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
   at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
   at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
   at System.Windows.FrameworkElement.ApplyTemplate()
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)

Ik probeer de dispatcher te vervangen:

deze _threadDispatcher = Dispatcher.CurrentDispatcher;

hiermee: _threadDispatcher = Application.Current.Dispatcher;

Maar het helpt niet. Bedankt voor advies.

MyObservableDicionary is geen afhankelijkheidsobject of eigenschap dependecy:

public class MyObservableDictionary<TKey, TValue> :
    IDictionary<TKey, TValue>,
    INotifyCollectionChanged,
    INotifyPropertyChanged
{..}

17
2018-01-14 11:56


oorsprong


antwoorden:


Ik kwam een ​​soortgelijke situatie tegen.

Ik heb een ObservableCollection van een klasse met de naam Person gekoppeld aan een datagrid en Person.SkinColor is SolidColorBrush.

Wat ik deed was het volgende:

foreach (Person person in personData)
{
 PersonModel person= new Person( );
 ......               
 personModel.SkinColor = new SolidColorBrush(person.FavoriteColor);
 personModel.SkinColor.Freeze();
 .....
}

23
2017-11-14 05:28



Gewoon een gok, maar taken worden standaard gemaakt op een achtergrondthread. Probeer uw taak te maken met behulp van de Task.Factory overbelasting met een SynchronizationContext. Ik weet niet zeker of het gebruik van de Dispatcher in een Taak werkt zoals je zou verwachten.

var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, uiContext);

Zodra u dat doet, zou u uw achtergrondeigenschap moeten kunnen wijzigen zonder de coördinator te gebruiken.


20
2018-01-14 21:26



Is uw gegevensbron een afhankelijkheidsobject? Als dit het geval is, moet dit ook op de UI-thread worden gemaakt. Meestal moet u uw gegevensbron niet van DependencyObject overnemen.


2
2018-01-14 12:25



Volledigheidshalve wil ik vermelden dat het goedgekeurde antwoord niet geschikt is als je een aantal voorwerpen hebt die niet erven freezable klasse. De standaard ObservableCollection laat alleen updates van de dispatcher toe, dus je hebt een thread-safe analoog nodig. Er zijn twee oplossingen van WPF-goeroe Dean Chalk wat lost het probleem op:

  1. Maak een thread-safe waarneembare verzameling. Het is een old school-oplossing die gewoon werkt. Om de broncode te verkrijgen, vinkt u a kort artikel in zijn blog.
  2. Gebruik Reactieve uitbreidingen bibliotheek. Zien Dit artikel bijvoorbeeld. Het is een beetje omvangrijk voor één taak, maar ondertussen brengt het een hele reeks moderne hulpmiddelen met zich mee die van pas komen.

UPDATE (31 juli 2015):

Links naar Dean Chalk's blog zijn dood, dus hier zijn alternatieven:

  • Veilige waarneembare verzameling: artikel, broncode.
  • Multi-threading, ObservableCollection, Reactive Extensions: artikel.

2
2017-08-23 00:09