This might totally be wrong, but I gather it's a mixture of deferred enumeration with WhereArrayIterator
, and the debugger attempting to enumerate it?
I get the feeling, where the immediate window is trying to enumerate your result, it is doing so on another thread (which is causing the CrossThreadMessagingException
).
It's not doing it when you call ToList
, because ToList
causes the enumeration to run immediately and concatenate the results in the list. This is done before you attempt to use the Count
method in the immediate window.
When you use Count()
without the ToList
call, it forces the WhereArrayIterator
(which is the return value of your Where
method call) to enumerate, which is then trying to access the your lamda delegate from another thread.
On testing, you can actually enumerate other instances of WhereArrayIterator
through immediate, so I think this is your particular use case, where you are trying to enumerate over the Process
type, which I think internally makes calls using the Win32 API.
Internally, the Process.MainWindowTitle
property uses lazy loading for its value. It doesn't actually make the call to grab the information, until the property is accessed for the first time (and also, it does so without locking, so if there where multiple threads accessing that area of the code, it is not atomic, so there is an inherit risk of race conditions - It shouldn't matter to much anyway, as it is a read only property, who's value should always be the same).
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[MonitoringDescription("ProcessMainWindowTitle")]
public string MainWindowTitle
{
get
{
if (this.mainWindowTitle == null)
{
IntPtr mainWindowHandle = this.MainWindowHandle;
if (mainWindowHandle == (IntPtr) 0)
{
this.mainWindowTitle = string.Empty;
}
else
{
StringBuilder lpString = new StringBuilder(Microsoft.Win32.NativeMethods.GetWindowTextLength(new HandleRef((object) this, mainWindowHandle)) * 2);
Microsoft.Win32.NativeMethods.GetWindowText(new HandleRef((object) this, mainWindowHandle), lpString, lpString.Capacity);
this.mainWindowTitle = ((object) lpString).ToString();
}
}
return this.mainWindowTitle;
}
}
When it is first accessed, the property makes a Win32 call to grab the window text. I believe this is where it seems to be falling over. But it only seems to fall over when using deferred enumeration with your WhereArrayIterator
instance.
This is all a blind guess to be honest!