3

You can find a lot of similar questions on SO, but no one (as I'm see) covers situation, when your logic must return something.

In this code example I have simple CustomMessageBox (it's a window), which must return something, entered by user.

public class CustomMessageBox  
{
  private string Value 
  {
      get 
      {
          return txt_box.Text;
      } 
  }

  private CustomMessageBox ()
  {
      InitializeComponent();
  }

  public static string Show(string caption = "Enter data")
  {
      CustomMessageBox cmb = new CustomMessageBox ();
      cmb.txt_block.Text = caption;

      cmb.ShowDialog();

      return cmb.Value;
  }
}

So when Show method called by BackgroundWorker, exception thrown at first line, when constructor tries to execute. Exception message is

An exception of type 'System.InvalidOperationException' occurred in 
PresentationCore.dll but was not handled in user code


Additional information: The calling thread must be STA,  
because many UI components require this.

Nothing new, but I can't find solutions for this problem, and I can't make thread to be STA. Show method signature must be clear like this — take string and return string.

How usually things like this must be resolved?

KeyNone
  • 8,745
  • 4
  • 34
  • 51
Arman Hayots
  • 2,459
  • 6
  • 29
  • 53
  • you can use dispatcher.Invoke to make thread to be STA – daniel Aug 19 '15 at 10:24
  • Any example with ability to return value from execution, please. – Arman Hayots Aug 19 '15 at 10:25
  • I usually did this the other way round (at least in WinForms): instead of returning something, I subscribed to the Close-event and fetched the value I needed within the event handler. – KeyNone Aug 19 '15 at 10:30
  • But I can't. A clear return required. – Arman Hayots Aug 19 '15 at 10:34
  • 1
    possible duplicate of [The calling thread must be STA, because many UI components require this](http://stackoverflow.com/questions/2329978/the-calling-thread-must-be-sta-because-many-ui-components-require-this) – theMayer Aug 22 '15 at 11:12

2 Answers2

2
public static string Show(string caption = "Enter data")
{
    Application.Current.Dispatcher.Invoke(new Action(() =>
    {
        CustomMessageBox cmb = new CustomMessageBox();
        cmb.txt_block.Text = caption;
        cmb.ShowDialog();
    }));
    return cmb.Value;
}
daniel
  • 1,010
  • 6
  • 15
  • «An exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll but was not handled in user code Additional information: The calling thread cannot access this object because a different thread owns it.» – Arman Hayots Aug 19 '15 at 10:36
  • Custom window created, but I'm still can't return value. – Arman Hayots Aug 19 '15 at 10:37
  • CustomMessageBox cmb = null; Application.Current.Dispatcher.Invoke(new Action(() => { cmb = new CustomMessageBox(); cmb.txt_block.Text = caption; cmb.ShowDialog(); })); return cmb.Value; – Arman Hayots Aug 19 '15 at 10:38
  • I know that it is possible to elicit this sort of behavior by doing convoluted dispatching. That is not a good solution to a problem of bad design. – theMayer Aug 19 '15 at 10:41
  • Have you try not use BackgroundWorker can return value? – daniel Aug 19 '15 at 10:42
  • Forget the question. Maybe you try include the logic to call the Show function in dispatcher. Like `Application.Current.Dispatcher.Invoke(new Action(() => { var value = CustomMessageBox.Show("Caption"); ... })` – daniel Aug 19 '15 at 10:58
2

You cannot call a UI component from a background worker. That is the proximate cause of your issue. All UI components must be created and interacted with from the UI thread. That is why we have some crazy logic in certain cases to invoke operations on UI components - there is only one UI thread running in the application.

A program that requires a UI element to be populated from a background process needs to be redesigned such that the operation is divided into two or more units of work, so that this requirement to operate the UI from the background is eliminated.

See WPF and background worker and the calling thread must be STA.

Community
  • 1
  • 1
theMayer
  • 15,456
  • 7
  • 58
  • 90
  • That explains why exceptions are being thrown. But how come I only see the exceptions in the debug output window? Why is it failing silently instead of displaying an error message? – Kyle Delaney May 15 '17 at 22:10
  • I'm not completely sure- usually you would not run a misconfigured program like this in production mode. – theMayer May 16 '17 at 16:25