Reputation: 2070
I want to understand how I can update my GUI with a simple text string on a regular basis. Essentially, I'm writing a twitter application which regularly polls twitter for updates. I want the contents of the update to be shown in a text block, one by one on a constant loop.
In order to keep the GUI responsive I need to perform the query in a background worker thread, however updating the GUI from this thread is not possible. As a learner, I'm struggling implement a way of updating the GUI by using events.
In my code below, I appreciated 'MainWindowGoUpdate' is going to be on the 'wrong thread' but how can I get the GUI thread to listen for the event?
A pointer appreciated.
public partial class MainWindow : Window
{
public MainWindow()
{
public static event UpdateTimeLineEvent _goUpdate;
public static string TheTimeLine;
UpdateTimeLine();
}
private void UpdateTimeLine()
{
txtb_timeline.Text = "Updating...";
BackgroundWorker startTimelineUpdater = new BackgroundWorker();
startTimelineUpdater.DoWork += new DoWorkEventHandler(startTimelineUpdater_DoWork);
startTimelineUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(startTimelineUpdater_RunWorkerCompleted);
startTimelineUpdater.RunWorkerAsync();
}
void startTimelineUpdater_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
Xtweet getSQL = new Xtweet();
var sqlset = getSQL.CollectLocalTimelineSql();
int i = 0;
while (i < 10)
{
foreach (var stringse in sqlset)
{
StringBuilder sb = new StringBuilder();
sb.Append(stringse[0] + ": ");
sb.Append(stringse[1] + " @ ");
sb.Append(stringse[2]);
sb.Append("\n");
TheTimeLine = sb.ToString();
_goUpdate += new UpdateTimeLineEvent(MainWindowGoUpdate);
_goUpdate.Invoke();
Thread.Sleep(10000);
i++;
}
}
}
}
void MainWindowGoUpdate()
{
txtb_timeline.Text = TheTimeLine;
}
void startTimelineUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
txtb_timeline.Text = "should not see this";
}
}
Upvotes: 1
Views: 8931
Reputation: 216343
I will try these change:
In your UpdateTimeLine add
startTimelineUpdater.WorkerReportsProgress = true;
startTimelineUpdater.ProgressChanged += new ProgressChangedEventHandler
(startTimelineUpdater_ProgressChanged);
In startTimelineUpdater_DoWork remove these lines
TheTimeLine = sb.ToString();
_goUpdate += new UpdateTimeLineEvent(MainWindowGoUpdate);
_goUpdate.Invoke();
and insert these:
BackgroundWorker bkgwk = sender as BackgroundWorker;
bkgwk.ReportProgress(0, sb.ToString());
finally add the progress event
private void startTimelineUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
txtb_timeline.Text = e.ObjectState.ToString();
}
Now you can leave only the call to UpdateTimeLine and remove the MainWindowGoUpdate method
Upvotes: 0
Reputation: 7915
You can use the Dispatcher class:
Dispatcher.BeginInvoke(
DispatcherPriority.Input, new Action(() =>
{
//update UI
}));
However in your case I would collect the results from the BackgroundWorker in a local variable and then change your label to loop through the results based on a WPF Timer
object.
Upvotes: 3
Reputation: 45106
Where you
txtb_timeline.Text = "should not see this";
Is where you get the results. Results will be in e.Result And you can pack e.Result with multiple properties.
If you want to get intermediate results you can use the progress.
Upvotes: 0
Reputation: 5197
You can use the Dispatcher to update your GUI. Check this blog post for a rather good example on how to do it.
Upvotes: 1