Reputation: 1257
I have a simple textbox in my program. Other features : another input from the user textbox1, and a button. Once the user enters a value in textbox1, and presses the button, I start to check and print messages to the user. My problem is that I don't see those messages on real time, one at a time. The messages appear at once, in the end. I didn't define data binding, because I thought that since it's a simple thing, I wouldn't need it, or am i wrong ? This is a very small portion of my program, it's in the button click event handler.
MainText.AppendText("Starting Refiling...\u2028");
foreach (DocumentData doc in Docs)
{
try
{
wsProxy.RefileDocument(doc);
MainText.AppendText(String.Format("Refilling doc # {0}.{1}\u2028", doc.DocNum, doc.DocVer));
}
catch (Exception exc)
{
if (exc.Message.Contains("Document is in use") == true)
MainText.AppendText(String.Format("There was a problem refilling doc # {0}, it is in use.\u2028",doc.DocNum));
else
MainText.AppendText(String.Format("There was a problem refilling doc # {0} : {1}.\u2028", doc.DocNum, exc.Message));
}
}
Upvotes: 0
Views: 2101
Reputation: 1827
You're doing all your looping/printing in the GUI thread. Basically you're giving it new items to show and not giving it time to show them. Create a background worker and let him do the work in the foreach loop that you posted. This should allow the UI thread to update the view as the text changes, instead of getting the one update at the end with all your changes. The link I posted includes examples on how to use the backgroundworker class, but here's what I'd do.
Create a background worker:
private readonly BackgroundWorker worker = new BackgroundWorker();
Initialize him:
public MainWindow()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
}
Create a task for him:
void worker_DoWork( object sender, DoWorkEventArgs e)
{
// Set up a string to hold our data so we only need to use the dispatcher in one place
string toAppend = "";
foreach (DocumentData doc in Docs)
{
toAppend = "";
try
{
wsProxy.RefileDocument(doc);
toAppend = String.Format("Refilling doc # {0}.{1}\u2028", doc.DocNum, doc.DocVer);
}
catch (Exception exc)
{
if (exc.Message.Contains("Document is in use"))
toAppend = String.Format("There was a problem refilling doc # {0}, it is in use.\u2028",doc.DocNum);
else
toAppend = String.Format("There was a problem refilling doc # {0} : {1}.\u2028", doc.DocNum, exc.Message);
}
// Update the text from the main thread to avoid exceptions
Dispatcher.Invoke((Action)delegate
{
MainText.AppendText(toAppend);
});
}
}
Start him when you get the button press event:
private void Button_Click(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync();
}
Upvotes: 1