简体   繁体   English

简单的C#代码会冻结自身和所有32位应用程序(包括VS2008),但前提是要在带有断点集的调试器下运行

[英]Simple C# code freezes itself and all 32-bit applications (incl. VS2008) but only if run under a debugger with a breakpoint set

Background: As part of a small winforms app I'm developing I have a login screen. 背景:作为一个正在开发的小型Winforms应用程序的一部分,我有一个登录屏幕。 Besides the standard username/password fields it also has a third field - "Location" which is a dropdown containing possible geographical locations where a user can log on. 除了标准的用户名/密码字段外,它还有第三个字段-“位置”,这是一个下拉列表,其中包含用户可以登录的可能地理位置。 The list of possible locations depends on the "distributor" to which the user belongs. 可能位置的列表取决于用户所属的“分发服务器”。 Think of it as a user group, it's nothing more than that in reality. 将其视为一个用户组,无非就是现实。

To provide user friendliness I change the contents of the dropdown whenever a valid username is entered. 为了提供用户友好性,每当输入有效的用户名时,我都会更改下拉菜单的内容。 Also the username textbox has autocomplete. 用户名文本框也具有自动完成功能。 Though this does offer some information disclosure, in this case it is not an issue. 尽管这确实提供了一些信息公开,但是在这种情况下,这不是问题。

The problem: When I type the first letter of my username in the textbox, autocomplete immediately completes it. 问题:当我在文本框中输入用户名的第一个字母时,自动完成功能会立即完成它。 The dropdown contents should also change. 下拉内容也应更改。 This happens fine if I run the program without debugger, but if the program is under debugger, everything freezes - both my app and Visual Studio. 如果我在没有调试器的情况下运行该程序,则情况会很好,但是如果该程序在调试器下,则所有内容都将冻结-我的应用程序和Visual Studio。 The autocomplete dropdown appears, but is empty. 出现自动完成下拉列表,但为空。 CPU usage is 0%. CPU使用率为0%。 Only when I kill my app does Visual Studio unfreeze. 只有当我杀死我的应用程序时,Visual Studio才会冻结。

What is weirder, moving one line of code fixes the problem, although semantically everything is the same. 奇怪的是,只移动一行代码就可以解决此问题,尽管从语义上讲,所有内容都是相同的。 Thus, this code works: 因此,此代码有效:

private void txtUser_TextChanged(object sender, EventArgs e)
{
    string EnteredUserName = this.txtUser.Text.Trim();
    var Found = this._NoLocations; 
    foreach ( var usr in this._AllUsers )
        if (string.Compare(usr.FullName, EnteredUserName, StringComparison.CurrentCultureIgnoreCase) == 0)
        {
            Found = new List<Business.Location>(this._AllLocations.Where((a, b) => a.Distributor == usr.Distributor));
            break;
        }
    this.bndLocation.DataSource = Found;
}

But this doesn't: 但这不是:

 private void txtUser_TextChanged(object sender, EventArgs e) { string EnteredUserName = this.txtUser.Text.Trim(); var Found = null; foreach ( var usr in this._AllUsers ) if (string.Compare(usr.FullName, EnteredUserName, StringComparison.CurrentCultureIgnoreCase) == 0) { Found = new List<Business.Location>(this._AllLocations.Where((a, b) => a.Distributor == usr.Distributor)); this.bndLocation.DataSource = Found; break; } if ( Found == null ) this.bndLocation.DataSource = this._NoLocations; } 

I can also set breakpoints in this method and it will show that the method completes just fine, but the freeze happens afterwards. 我还可以在此方法中设置断点,这将表明该方法可以很好地完成,但是冻结随后会发生。

What gives? 是什么赋予了?

Oh, almost forgot - I'm using Visual Studio 2008 and Telerik RadControls Q3 2009. This didn't happen with windows standard controls, it only appeared after migration. 哦,差点忘了-我使用的是Visual Studio 2008和Telerik RadControls Q32009。Windows标准控件不会发生这种情况,它只会在迁移后出现。 Still, very weird. 仍然,很奇怪。

Update 1: OK, so the second code fragment only works sometimes . 更新1:好的,因此第二个代码片段有时只能工作。 But here's something weirder: it's not only VS2008 that freezes. 但是这里有些奇怪:不仅仅是VS2008冻结了。 My browser (Opera) and Windows Live! 我的浏览器(Opera)和Windows Live! Messenger also became unresponsive. Messenger也变得反应迟钝。 Thankfully the Task Manager and the Taskbar work just fine. 幸运的是,任务管理器和任务栏工作正常。 This is getting more and more confusing... 这越来越令人困惑...

Update 2: The variables _AllUsers , _AllLocations and _NoLocations are simple generic List<T> s. 更新2:变量_AllUsers_AllLocations_NoLocations是简单的通用List<T> The User and Location classes are simple objects with simple properties. UserLocation类是具有简单属性的简单对象。 Although I am using NHibernate, so they might be automagically subclassed to something. 尽管我正在使用NHibernate,所以它们可能会自动地被子类化。 bndLocation is the standard .NET BindingSource to which the Locations dropdown is bound. bndLocation是“位置”下拉列表绑定到的标准.NET BindingSource

Update 3: Wow, apparently all 32-bit processes are frozen . 更新3:哇,显然所有32位进程都被冻结了 Or at least those with a UI. 或至少具有UI的用户。 I'm able to start new apps, and they manage to initialize and show up, but then they freeze. 我能够启动新的应用程序,并且它们能够初始化并显示,但是随后冻结。 For the record, I'm running Windows 7 x64. 作为记录,我正在运行Windows 7 x64。

Update 4: Here's the catch for Update 1: the code works if there are no breakpoints set in code. 更新4:这是更新1的要点:如果代码中未设置断点,则代码可以工作。 If there is a breakpoint set anywhere, it will freeze. 如果在任何地方设置了断点,它将冻结。 The breakpoint doesn't have to be hit, it just has to be set. 不必设置断点,只需设置断点即可。 If I set the breakpoint after starting the program, all will be fine. 如果我在启动程序后设置了断点,一切都会好的。

Update 5: As per request, here's the stack trace for the event: 更新5:根据请求,以下是事件的堆栈跟踪:

ServiceTracker.exe!ServiceTracker.Forms.Login.txtUser_TextChanged(object sender = {Telerik.WinControls.UI.RadTextBox}, System.EventArgs e = {System.EventArgs}) Line 85 C#
System.Windows.Forms.dll!System.Windows.Forms.Control.OnTextChanged(System.EventArgs e) + 0x68 bytes    
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadTextBoxBase.textBoxItem_TextChanged(object sender = {Telerik.WinControls.UI.RadTextBoxItem}, System.EventArgs e = {System.EventArgs}) + 0x47 bytes 
[Native to Managed Transition]  
[Managed to Native Transition]  
Telerik.WinControls.dll!Telerik.WinControls.RadItem.OnTextChanged(System.EventArgs e = {System.EventArgs}) + 0x80 bytes 
Telerik.WinControls.dll!Telerik.WinControls.RadItem.OnPropertyChanged(Telerik.WinControls.RadPropertyChangedEventArgs e = {Telerik.WinControls.RadPropertyChangedEventArgs}) + 0xeb bytes   
Telerik.WinControls.dll!Telerik.WinControls.RadHostItem.OnPropertyChanged(Telerik.WinControls.RadPropertyChangedEventArgs e = {Telerik.WinControls.RadPropertyChangedEventArgs}) + 0x5a bytes   
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadTextBoxItem.OnPropertyChanged(Telerik.WinControls.RadPropertyChangedEventArgs e = {Telerik.WinControls.RadPropertyChangedEventArgs}) + 0x36c bytes 
Telerik.WinControls.dll!Telerik.WinControls.RadObject.RaisePropertyNotifications(Telerik.WinControls.RadPropertyValue propVal = {Telerik.WinControls.RadPropertyValue}, object oldValue = "", object newValue = "v") + 0x2f7 bytes  
Telerik.WinControls.dll!Telerik.WinControls.RadObject.SetValueCore(Telerik.WinControls.RadPropertyValue propVal = {Telerik.WinControls.RadPropertyValue}, object propModifier = null, object newValue = "v", Telerik.WinControls.ValueSource source = Local) + 0x5bb bytes  
Telerik.WinControls.dll!Telerik.WinControls.RadElement.SetValueCore(Telerik.WinControls.RadPropertyValue propVal = {Telerik.WinControls.RadPropertyValue}, object propModifier = null, object newValue = "v", Telerik.WinControls.ValueSource source = Local) + 0xa2 bytes  
Telerik.WinControls.dll!Telerik.WinControls.RadObject.SetValue(Telerik.WinControls.RadProperty property = {Telerik.WinControls.RadProperty}, object value = "v") + 0x9b bytes   
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadTextBoxItem.TextBoxControl_TextChanged(object sender = {Text = "v"}, System.EventArgs e = {System.EventArgs}) + 0x168 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.OnTextChanged(System.EventArgs e) + 0x68 bytes    
System.Windows.Forms.dll!System.Windows.Forms.TextBoxBase.WmReflectCommand(ref System.Windows.Forms.Message m) + 0xd2 bytes 
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.HostedTextBoxBase.WndProc(ref System.Windows.Forms.Message message = {msg=0x2111 (WM_REFLECT + WM_COMMAND) hwnd=0xf0478 wparam=0x3000478 lparam=0xf0478 result=0x0}) + 0x5ac bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x46 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 8465, System.IntPtr wparam, System.IntPtr lparam) + 0xad bytes  
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Control.SendMessage(int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x6c bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.ReflectMessageInternal(System.IntPtr hWnd, ref System.Windows.Forms.Message m) + 0x46 bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.WmCommand(ref System.Windows.Forms.Message m) + 0x44 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x1fd bytes 
Telerik.WinControls.dll!Telerik.WinControls.RadControl.WndProc(ref System.Windows.Forms.Message m = {msg=0x111 (WM_COMMAND) hwnd=0xc046e wparam=0x3000478 lparam=0xf0478 result=0x0}) + 0x1ab bytes 
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.RadTextBoxBase.WndProc(ref System.Windows.Forms.Message m = {msg=0x111 (WM_COMMAND) hwnd=0xc046e wparam=0x3000478 lparam=0xf0478 result=0x0}) + 0x7a bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x46 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 273, System.IntPtr wparam, System.IntPtr lparam) + 0xad bytes   
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DefWndProc(ref System.Windows.Forms.Message m) + 0x9f bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x9e6 bytes 
Telerik.WinControls.UI.dll!Telerik.WinControls.UI.HostedTextBoxBase.WndProc(ref System.Windows.Forms.Message message = {msg=0x102 (WM_CHAR) hwnd=0xf0478 wparam=0x76 lparam=0x2f0001 result=0x0}) + 0x5ac bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x46 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 258, System.IntPtr wparam, System.IntPtr lparam) + 0xad bytes   
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x5c3 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = 4, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.Application.ModalApplicationContext}) + 0x578 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x65 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window owner) + 0x763 bytes    
ServiceTracker.exe!ServiceTracker.Forms.Login.Authentificate(out ServiceTracker.Business.User user = null, out ServiceTracker.Business.Location location = null) Line 30 + 0x12 bytes   C#
ServiceTracker.exe!ServiceTracker.Framework.Program.Main() Line 79 + 0x19 bytes C#
[Native to Managed Transition]  
[Managed to Native Transition]  
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x47 bytes  
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x9b bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x4d bytes   

Update 6: So, I've come as far as to strongly suspect that there is a combination of a deadlock and a race condition somewhere between my app and other 32-bit apps. 更新6:因此,我甚至强烈怀疑我的应用程序与其他32位应用程序之间某个地方存在死锁和竞争状态的组合。 Which is strange, because even under a debugger the process is 64-bit. 这很奇怪,因为即使在调试器下,进程也是64位的。 Anyways, here are the several possible scenarios that reproduce the problem: 无论如何,这是重现此问题的几种可能情况:

  • The method changes the dropdown contents and there is a breakpoint ANYWHERE in my code. 该方法更改了下拉菜单的内容,并且我的代码中存在一个断点。 However if the breakpoint is OUTSIDE the if statement in the above method, everything works. 但是,如果断点在上述方法的if语句之外,则一切正常。 Possibly that is because the breakpoint gets hit twice in a row - first when I enter the first letter; 可能是因为断点连续两次被击中-首先是当我输入第一个字母时; second when the autocomplete has provided the rest of the username. 当自动完成功能提供了其余用户名时,第二个。
  • If the method doesn't change the dropdown contents, but there is a breakpoint inside the if statement, everything freezes as well. 如果该方法不更改下拉菜单的内容,但是if语句中有一个断点,则所有内容也会冻结。
  • If the method contains just a Thread.Sleep(1000); 如果该方法仅包含Thread.Sleep(1000); , there is a freeze for exactly 1 second; ,精确冻结1秒钟;
  • Otherwise no freeze. 否则不冻结。

So it smells like the event handler (or rather some method up the stack) takes a lock on some global resource which all other 32-bit processes need. 因此,闻起来像事件处理程序(或栈中的某种方法)对所有其他32位进程需要的某些全局资源进行了锁定。 Since VS2008 is a 32-bit process, it has to wait. 由于VS2008是32位进程,因此必须等待。 But since there is a brekpoint, my app isn't running either, hence the deadlock. 但是由于存在问题,我的应用程序也没有运行,因此陷入了僵局。 Also, changing the dropdown contents tries to take the same lock, and thus there is a deadlock within my app. 另外,更改下拉菜单内容会尝试使用相同的锁定,因此我的应用程序中存在死锁。 If however there is a pause beforehand (when the breakpoint gets hit twice), the race condition doesn't happen and everything works again. 但是,如果事先有一个暂停(当断点两次被击中时),则不会发生竞争状况,并且一切都会恢复。

But... I cannot imagine what this global resource could be. 但是...我无法想象这种全球资源可能是什么。

I don't know what your problem is, but I can point out some things that you are doing which could be causing problems: 我不知道您的问题是什么,但是我可以指出您正在做的一些事情可能会引起问题:

  1. Access to modified closure within lambda expression: 在lambda表达式中访问修改后的闭包:

You should not access "usr" within a lambda expression since it is a closure within the foreach loop, and you can get some really weird behavior here. 您不应该在lambda表达式中访问“ usr”,因为它是foreach循环中的闭包,并且您可以在此处得到一些非常奇怪的行为。 (the value of "usr" will be taken as the last one instead of the one it was created with. (“ usr”的值将被当作最后一个而不是其创建时的值。

It doesn't seem to me that this would be your problem. 在我看来,这不是您的问题。 To see if it is, do this: 若要查看是否这样做,请执行以下操作:

var usrTemp = usr;
Found = new List<Business.Location>(this._AllLocations.Where((a, b) => a.Distributor == usrTemp.Distributor));
  1. I don't know what kind of LINQ provider you are using, or what your OnItemBound events look like, but in the first example you are biding your items when you still have an iterator open on _AllUsers. 我不知道您使用的是哪种LINQ提供程序,或者您的OnItemBound事件是什么样的,但是在第一个示例中,当您还在_AllUsers上打开迭代器时,您正在对项目进行出价。 If your business layer isn't written as to support this concurrent access, this might be causing a problem. 如果您的业务层不是为支持此并发访问而编写的,则可能会引起问题。

To see if this is a problem change the foreach loop: 要查看是否存在问题,请更改foreach循环:

foreach (var usr in this._AllUsers.ToArray())

您是否排除了可能为此this.bndLocation.DataSource的访问器属性(可能在其他线程中)断点的d'oh选项?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM