0

I would like to update the Text of a TextBlock in a WPF app. I am using a BackgroundWorker which makes an asynchronous call to an update method.

Edit:

I had look at question: Progress Bar update from Background worker stalling before posting. Where my problem differs is that I only want to change the text to "Loading..." in before a call to a potentially long running service call. I would like my implementation to be as reusable as possible and don't need to and can't keep track of progress. I then intend to change the textblock text back to its previous message.

I have modelled the problem in a new WPF project and am getting the same issue.

The text is changed to "Loading..." at the beginning of a datagrid begin cell edit event and is set back to its previous value when the necessary data is loaded.

My issue at the moment is that the text appears to change to "Loading..." and back again instantly, at the end of the cell begin edit event. I am certain that there is a significant time between the calls, even trying Wait(10000). I do not see the "Loading" text when I run it.

My implementation (note: I have already tried removing the using enclosing, no change):

using(BackgroundWorker bw = new BackgroundWorker())
{
    bw.WorkerReportsProgress = true;
    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

    bw.RunWorkerAsync("Loading...");
};

The code above is called within grdBlah_BeginningEdit is called again after the data is grabbed, with the text changed.

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        if (((BackgroundWorker)sender).CancellationPending)
        {
            e.Cancel = true;
            return;
        }

        UpdateDelegate update = new UpdateDelegate(UpdateText);
        this.Dispatcher.BeginInvoke(update, e.Argument);
        // I have also tried: txtSearchCollection.Dispatcher.BeginInvoke(update, e.Argument);
    }
    catch (Exception ex)
    {
        bool brake = true;  // used to apply a breakpoint
    }
}

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        try
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            worker.DoWork -= new DoWorkEventHandler(bw_DoWork);
        }
        catch (Exception ex)
        {
            bool brake = true;
        }
    }

private delegate void UpdateDelegate(string s);

private void UpdateText(string s)
{
    txtSelectedCollection.Text = s;
}

Any help would be greatly appreciated.

tjheslin1
  • 1,378
  • 6
  • 19
  • 36
  • 1
    Did you see the ProgressChanged event of the BackgroundWorker? It's designed to update UI. – Max May 28 '14 at 09:32
  • 2
    What's in `RunWorkerCompleted`? The current `DoWork` method will finish instantly. – amnezjak May 28 '14 at 09:32
  • And I thought lambda expressions were far from being clean... Try `bw.DoWork += (s, e) => { try { if (((BackgroundWorker)sender).CancellationPending) { e.Cancel = true; return; } this.Dispatcher.Invoke((MethodInvoker) ( () => { txtSelectedCollection.Text = e.Argument; } )); }` – Kilazur May 28 '14 at 09:36
  • I will look into ProgressChanged and update the question with my RunWorkerCompleted method. Thanks. – tjheslin1 May 28 '14 at 09:39
  • 2
    I would advise AGAINST using the BackgroundWorker is possible. Use `async` `await` instead. Its much easier to use. – Aron May 28 '14 at 09:48
  • Adding Progressed changed within an interim message seems to have no affect and the interim message never appears. – tjheslin1 May 28 '14 at 09:48
  • You have to call the ReportProgress method of the Backgroundworker to raise the ProgressChangedEvent. – Max May 28 '14 at 09:53
  • Cheers @Max I've updated my question with the code change. Sadly what happens now is I'm stuck with the text set by the progress changed event. – tjheslin1 May 28 '14 at 12:39
  • Why do you use BackgroundWorker? I suggest you to use async/await. Have a look at this article - http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx – Sasha May 28 '14 at 13:11
  • @Sheridan Can you have a read of my edit, in bold, as I believe it justifies this question being unique and I haven't been able to progress on this problem. Thanks – tjheslin1 Jun 01 '14 at 14:31
  • I accept your reasoning and have re-opened your question, although I question your reasoning for showing your `BackgroundWorker` code if this question doesn't really relate to it. It seems to me as though you just need to call `Dispatcher.Invoke` with your call to change the `TextBlock`. – Sheridan Jun 02 '14 at 07:48

0 Answers0