Click here to Skip to main content
15,891,253 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am developing a multi-threaded monitor application. In addition to the "main" thread, there are 2 sets of reader-writer threads connecting to 2 instances of a production application. Part of the message flow from the production apps are EvtMsg items. These are placed by the reader thread into a ConcurrentQueue for that particular side (LEFT or RIGHT). The main window has an EvtMsg button for each side. When you click on one of them, it will bring up a window that contains a DataGrid, populated from the given ConcurrentQueue.

The problem is when I open an EvtMsg window, the DataGrid is populated with all EvtMsg objects received up to that point (say, for example, 3 items), but upon receiving new EvtMsg messages, they don't update the window (I am using INotifyPropertyChanged, and I have debugged to verify that the ConcurrentQueue has the new items).

Data structures:
C#
public enum eSide : int { LEFT = 0, RIGHT = 1 }
public const int C_numSides = 2;
// ....

public class EvtMsg : INotifyPropertyChanged
{
    public  ulong        sequenceNumber         { get; set; }
    public  string       description            { get; set; }
    // ....
}

public class AnEvtQueue : INotifyPropertyChanged
{
    public ConcurrentQueue<EvtMsg> EvtQueue { get; set; }

    public AnEvtQueue()
    {
        EvtQueue = new ConcurrentQueue<EvtMsg>();
    }
    // ....
}

public class EvtHandler : INotifyPropertyChanged
{
    public AnEvtQueue[]     Sides     {get; set;}

    public EvtHandler()
    {
        Sides = new AnEvtQueue[C_numSides];
        Sides[(int)eSide.LEFT ] = new AnEvtQueue();
        Sides[(int)eSide.RIGHT] = new AnEvtQueue();
    }
    // ....
    public void AddEvtMsg(eSide WhichSide, EvtMsg msg)
    {
        Sides[side].EvtQueue.Enqueue(msg);
    }
    // ....
}

xaml:
C#
<DataGrid Grid.Row="2"
          AutoGenerateColumns="False"
          IsReadOnly="True"
          SelectionMode="Single"
          SelectionUnit="FullRow"
          GridLinesVisibility="None"
          Name="StatList"
          ItemsSource="{Binding NotifyOnSourceUpdated=True}">
    <DataGrid.Columns>
        <!-- Col 0: Sequence # -->
        <DataGridTextColumn Binding="{Binding Path=sequenceNumber}"
                        ElementStyle="{StaticResource DGCell_RightAlignStyle}"
                        Header="Sequence #" />

        <!-- Col 0: EvtMsg Text -->
        <DataGridTextColumn Binding="{Binding Path=description}"
                            FontFamily="Courier New"
                            Header="EvtMsg Text" />
    </DataGrid.Columns>
</DataGrid>

<!--     ....     -->

Code-behind:
C#
    public EvtMsgWindow(eSide WhichSide)
    {
        public ApplicationViewModel AppVM = ApplicationViewModel.Instance;
        InitializeComponent();

        StatList.ItemsSource = AppVM.TheEvtHandler.Sides[(int)WhichSide].EvtQueue;
    }
}


What I have tried:

I had tried an ObservableCollection, but this didn't seem to work with multiple threads (socket thread adds, GUI thread reads).
Posted
Updated 25-Jun-20 4:23am
Comments
[no name] 23-Jun-20 16:29pm    
It didn't "seem" to work is not a reason to discard the preferred solution. Use a multi-theeaded "proxy" if you have to.

1 solution

For WPF to see the changes to a collection, it needs to implement the INotifyCollectionChanged interface[^].

You are using the ConcurrentQueue<T> class[^], which doesn't implement this interface. Therefore, WPF will not be notified when you update the collection, and will not update any controls bound to it.

You'll either need to use an ObservableCollection<T> and provide your own locking to ensure thread-safety, or create your own collection class to wrap the ConcurrentQueue and raise the CollectionChanged event when the collection is updated.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900