Dave
Dave

Reputation: 8461

Cross thread error despite setting ApartmentState

I am trying to do display the content of a loop to my UI. First off, I'm not sure I'm approaching this the correct way (using WinForms) but this is what I'm doing:

foreach (string item in stringArray)
{
        Thread thread = new Thread(delegate()
                              {
                                  UpdatedResultEvent(item);
                              });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
}

I hope this is enough information, but if it isn't then I'll go into more detail here.

I have 2 classes, my Program.cs (WinForm) and another class called logicClass. I pass an instance of my Program object to my logicClass. My logicClass has a delegate which signature matches a method in my Program class. The method which is passed as a delegate is

public void UpdateResultsOnScreen(string newContent)
{
txtResults.Text += newContent;
}

The error message is

Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

EDIT

The goal is, similar to a way the progress bar works, is to see the Control getting updated in real time. Currently, even if it does work, the thread doesn't return the 'results' to the screen until the thread is complete.

Upvotes: 0

Views: 155

Answers (3)

Moha Dehghan
Moha Dehghan

Reputation: 18472

Use this (if you are on WinForms):

public void UpdateResultsOnScreen(string newContent)
{
    txtResults.BeginInvoke(
        new Action<string>((value) =>
        {
            txtResults.Text += value;
        }),
        newContent);
}

Also as animaonline said, consider using ThreadPool or Parallel.ForEach.

Upvotes: 1

nsconnector
nsconnector

Reputation: 836

How about doing this??

 public void UpdateResultsOnScreen(string newContent)
    {
        if(txtResults.InvokeRequired)
        {
            txtResults.Invoke(
                new Action<string>(content => txtResults.Text += content), newContent);
            return;
        }
        txtResults.Text += newContent;
    }

Upvotes: 0

animaonline
animaonline

Reputation: 3804

Even though you are setting the ApartmentState, the UI controls must be invoked when accessed from another (Non-UI) thread.

Make sure you invoke your UI controls inside your UpdateResultEvent method.

Anyways, what you're doing is not a good idea, consider using a ThreadPool or Parallel.ForEach

It will automatically scale your code, spawning a bunch of threads can really decrease the performance, especially if your collection has a lot of items in it.

Upvotes: 1

Related Questions