2

I would like to make my getter thread safe. When I do this, I get an error:

public ApplicationViewModel SelectedApplication
    {
        get
        {
            if (InvokeRequired)
            {
                BeginInvoke((Action<ApplicationViewModel>)SelectedApplication);
            }

            return _applicationsCombobox.SelectedItem as ApplicationViewModel;
        }
    }

I have the error:

Cannot cast expression of type 'Foo.Model.ApplicationViewModel' to type 'Action<ApplicationViewModel>'
Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
John
  • 4,351
  • 9
  • 41
  • 57

3 Answers3

6

Lots of things wrong:

  • you cannot use BeginInvoke, Invoke is required
  • you cannot use Action<>, you are returning a value so Func<> is required
  • you cannot also run the original code after invoking, else is required.

Which produces:

public ApplicationViewModel SelectedApplication
{
    get
    {
        if (this.InvokeRequired)
            return (ApplicationViewModel)this.Invoke(new Func<ApplicationViewModel>(() => this.SelectedApplication));
        else
            return _applicationsCombobox.SelectedItem as ApplicationViewModel;
    }
}

Hiding the thread context switches in a low-level property is usually a mistake. Invoking has lots of overhead, the resulting code may end up being very slow without a good hint of why it is so slow.

Bitterblue
  • 13,162
  • 17
  • 86
  • 124
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Except it's transparent to the consumer; no other method has to care how it was invoked in order to get this property in a synchronous fashion. You'd only be able to reduce the slowdown in cases where you were 100% sure the caller was on the UI thread. – KeithS Aug 04 '11 at 17:34
3

BeginInvoke takes a delegate.

You can write

return (ApplicationViewModel)Invoke(new Func<object>(() => applicationsCombobox.SelectedItem));
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

Try:

public ApplicationViewModel SelectedApplication
    {
        get
        {
            if (InvokeRequired)
            {
                BeginInvoke(() => { return SelectedApplication(); });
            }

            return _applicationsCombobox.SelectedItem as ApplicationViewModel;
        }
    }
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • Thanks but now it says: "Method, event or delegate is expected" on the method SelectedApplication(); – John Aug 04 '11 at 17:11