Search code examples
c#backgroundworker

Backgroundworker exits after first expression


I have a list view bound to an ObservableCollection. With that I want to mock a chat application with a WPF gui. To simulate some activity I wanted to use a Background worker who spams a little bit. But the worker always exits his loop after executing the first statment, so my question is: why does he do that and how to fix it?
here is the code so far:

  public partial class MainWindow : Window, INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    private string pCurrentUsername;
    public string currentUsername
    {
        get { return pCurrentUsername; }
        set
        {
            pCurrentUsername = value;
            if (null != this.PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("currentUsername"));
            }
        }
    }

    ObservableCollection<ChatPost> items = new ObservableCollection<ChatPost>();
    BackgroundWorker bgWorker = new BackgroundWorker();

    public MainWindow()
    {
        InitializeComponent();
        currentUsername = "Me";
        items.Add(new ChatPost("this", "that"));

        bgWorker.DoWork += new DoWorkEventHandler(mockBussiness);
        bgWorker.RunWorkerAsync();
        lvChat.ItemsSource = items;

    }

    private void mockBusiness(object o, DoWorkEventArgs args)
    {
        while (!bgWorker.CancellationPending)
        {  
            items.Add(new ChatPost("guy1", "Ey man!"));
            items.Add(new ChatPost("guy2", "What man?"));
        }

    }


    private void btSend_Click(object sender, RoutedEventArgs e)
    {
        items.Add(new ChatPost(currentUsername, tbMessage.Text));
    }
}

public class ChatPost
{
    public ChatPost()
    { }
    public ChatPost(string username, string message)
    { 
        this.username = username;
        this.message = message;
    }
    public string username { get; set; }
    public string message { get; set; }
}

So the only thing that gets executed (meaning printed) is one time "Ey man!"


Solution

  • Yes, you're modifying the UI (indirectly, through the ObservableCollection<>) on a non-UI thread. You're not allowed to do that. I suspect you should find an exception being thrown giving that detail, although it may not be easy to find.

    You need to marshal back to the UI thread for any threading operations, in general. If you're using WPF on .NET 4.5, apparently you can using BindingOperations.EnableCollectionSynchronization for this, but I admit I have no direct experience of this.