Search code examples
c#wpfmultithreadingbackgroundworker

Try to write from the background worker to a textbox in the GUI


I've spend now over 2 hours trying to resolve this issue and it would be awesome if someone could help me .. :)

Basically, what I try to to is an application which queries a database with LINQ and webservices and retrieves informationen.

From the result I extract few informations and write them to a .CSV file.

Everything works perfectly, except the logging.

Since I dont want that my UI frezzes, I've implemented a background worker:

I hand my logger textbox over to the background worker, that I write the progress from my static webservice methods.

using TextBoxAsAlias = System.Windows.Controls.TextBox;

Here I write for the first time to the logger textbox, which works absolutely perfect.

private void btnExecute_Click_1(object sender, RoutedEventArgs e)
        {
            // Register background worker
            worker.DoWork += worker_DoWork;
            worker.RunWorkerCompleted += worker_RunWorkerCompleted;

            // Flush the content of the logger textbox
            txtboxLogger.Clear();
            txtboxLogger.AppendText("#########################" + Environment.NewLine);
            txtboxLogger.AppendText("# Logger - " + DateTime.Now.ToString("T") + "#" + 
        txtboxLogger.AppendText("#########################" + Environment.NewLine + Environment.NewLine);


        worker.RunWorkerAsync(new Object[] {txtboxLogger });

            }

Here is where I get the problem:

As you can see I try again to log some text in the DoWork method. The problem is, that the whole text will just be logged when the worker_DoWork has finished. So as result I wait for 5minutes and nothing happens in the logger textbox and as soon as it finished, everything gets written at once.

void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Object[] parameter = (Object[])e.Argument;
            TextBoxAsAlias textboxLogger = (TextBoxAsAlias)parameter[0];

            textboxLogger.Dispatcher.InvokeAsync((Action)(() =>
            {
                txtboxLogger.AppendText(DateTime.Now.ToString("T") + " - Start processing ... " + Environment.NewLine);

                if (isAutoSelection)
                {
                    // Execute Webservice with auto selection
                    RandomDoWorkMethod(null, context, credential, dateStart, textboxLogger);
                }

                else
                {
                    // Read în the Numbers + hand it over to the webservice for further computing
                    RandomDoWorkMethod(ReadInputFile(), context, credential, dateStart, textboxLogger);
                }

            }));
        }

Does anyone know how I can write immediately during the background Worker to the log file and not just at the end?

I make further use of the following code in my other methods, but the result is still the same, because all of them are in the worker_DoWork thread.

textboxLogger.Dispatcher.InvokeAsync((Action)(() =>
            {
))};

Thanks in advance for your help.

Regards

George


Solution

  • Use SynchronizationContext of your UI thread.

    Global variable:

    private System.Threading.SynchronizationContext _uiSyncContext;
    

    In constructor:

    this._uiSyncContext = System.Threading.SynchronizationContext.Current;
    

    Working with UI elements in worker_DoWork method:

    this._uiSyncContext.Post(
      delegate(object state)
      {
        txtboxLogger.AppendText(state as string);
      },
      "Your Text"
    );
    

    You can also use Send (Synchronous) method instead of Post (Asynchronous).