初始代码是:
var processes = Process.GetProcesses().Where(p => p.MainWindowTitle.ToUpperInvariant().Contains("FOO"));
在调试期间,如果我尝试在即时窗口窗格中的Count()
上调用processes
或检查本地窗格中的“结果视图”,则会得到CrossThreadMessagingException
。如果我不调试但只运行代码,一切都很好。如果我将集合转换为列表,然后将其分配给processes
并在调试期间使用Count
属性,那也没关系。
CrossThreadMessagingException
究竟是什么?为什么IEnumerable
方法会造成这种异常?
编辑:提供有关异常的更多信息。
消息:发生异常'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException'
来源:Microsoft.VisualStudio.Debugger.Runtime
堆栈跟踪:
at Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException(String formatString)
at Microsoft.Win32.NativeMethods.GetWindowTextLength(HandleRef hWnd)
在System.Diagnostics.Process.get_MainWindowTitle()
答案 0 :(得分:3)
这可能完全是错的,但我收集它是延迟枚举与WhereArrayIterator
的混合,并且调试器试图枚举它?
我感觉到,即时窗口试图枚举你的结果,它是在另一个线程上执行的(导致CrossThreadMessagingException
)。
当您调用ToList
时,它不会执行此操作,因为ToList
会导致枚举立即运行并在列表中连接结果。在您尝试在即时窗口中使用Count
方法之前完成此操作。
如果您在没有Count()
调用的情况下使用ToList
,则会强制WhereArrayIterator
(这是您的Where
方法调用的返回值)枚举,然后试图从另一个线程访问你的lamda委托。
在测试中,您实际上可以通过立即枚举WhereArrayIterator
的其他实例,所以我认为这是您的特定用例,您尝试枚举Process
类型,我认为使用Win32 API进行调用。
在内部,Process.MainWindowTitle
属性使用延迟加载作为其值。它实际上并没有调用抓取信息,直到第一次访问该属性(并且,它没有锁定,所以如果有多个线程访问该代码区域,那么它是不是原子的,所以存在种族条件的继承风险 - 无论如何它都无关紧要,因为它是一个只读属性,它的值应该始终是相同的)。
[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;
}
}
首次访问时,属性会调用Win32来获取窗口文本。我相信这是它似乎正在倒下的地方。 但只有在您的WhereArrayIterator
实例中使用延迟枚举时才会出现问题。
说实话,这是一个盲目的猜测!