Справочная информация: Как часть небольшого приложения winforms, которое я разрабатываю, у меня есть экран входа в систему.Помимо стандартных полей имени пользователя и пароля у него также есть третье поле - «Местоположение», которое представляет собой раскрывающийся список, содержащий возможные географические местоположения, в которые пользователь может войти.Список возможных местоположений зависит от «дистрибьютора», к которому принадлежит пользователь.Думайте об этом как о группе пользователей, в действительности это не что иное, как это.
Чтобы обеспечить удобство для пользователя, я изменяю содержимое раскрывающегося списка всякий раз, когда вводится правильное имя пользователя.Также в текстовом поле имени пользователя есть автозаполнение.Хотя это и дает раскрытие некоторой информации, в данном случае это не проблема.
Проблема: Когда я набираю первую букву моего имени пользователя в текстовом поле, автозаполнение немедленно завершает его.Содержимое выпадающего списка также должно измениться.Это происходит нормально, если я запускаю программу без отладчика, но если программа находится под отладчиком, все зависает - и мое приложение, и Visual Studio.Раскрывающийся список автозаполнения появляется, но он пуст.Загрузка процессора составляет 0%.Только когда я убиваю свое приложение, Visual Studio размораживается.
Что страннее, перемещение одной строки кода решает проблему, хотя семантически все одинаково.Таким образом, этот код работает:
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;
}
Но это не так:
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;
}
Я также могу установить точки останова в этом методеи это покажет, что метод завершается просто отлично, но потом происходит остановка.
Что дает?
О, почти забыл - я использую Visual Studio 2008 и Telerik RadControls Q3 2009.Это не произошло со стандартными элементами управления Windows, оно появилось только после миграции.Тем не менее, очень странно.
Обновление 1: ОК, поэтому второй фрагмент кода работает только иногда .Но вот кое-что более странное: не только VS2008 зависает.Мой браузер (Opera) и Windows Live!Мессенджер тоже стал не отвечать.К счастью, диспетчер задач и панель задач работают просто отлично.Это становится все более запутанным ...
Обновление 2: Переменные _AllUsers
, _AllLocations
и _NoLocations
являются простыми обобщенными List<T>
с.Классы User
и Location
являются простыми объектами с простыми свойствами.Хотя я использую NHibernate, они могут быть автоматически разделены на что-либо.bndLocation
- это стандартный .NET BindingSource
, к которому привязан раскрывающийся список Locations.
Обновление 3: Ух, очевидно все 32-битные процессы заморожены ,Или, по крайней мере, те, с интерфейсом.Я могу запускать новые приложения, и им удается инициализировать и показать, но затем они зависают.Для записи, я использую Windows 7 x64.
Обновление 4: Вот подвох для Обновления 1: код работает, если в коде не установлены точки останова.Если где-либо установлена точка останова, она замерзнет.Точка останова не должна быть достигнута, она просто должна быть установлена.Если я установлю точку останова после запуска программы, все будет хорошо.
Обновление 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
Обновление 6: Итак, я дошел до того, что сильно подозреваю, что где-то между моим приложением и другими 32-разрядными приложениями существует комбинация тупика и состояния гонки.Что странно, потому что даже под отладчиком процесс 64-битный.В любом случае, вот несколько возможных сценариев, которые воспроизводят проблему:
- Метод изменяет содержимое раскрывающегося списка, и в моем коде есть точка останова ВСЕГДА.Однако, если точка останова находится за пределами оператора
if
в вышеприведенном методе, все работает.Возможно, это связано с тем, что точка останова попадает дважды подряд - сначала при вводе первой буквы;второй, когда автозаполнение предоставило оставшееся имя пользователя. - Если метод не изменяет содержимое раскрывающегося списка, но в операторе
if
есть точка останова, все также зависает. - Если метод содержит только
Thread.Sleep(1000);
, происходит остановка ровно на 1 секунду;
- В противном случае нет заморозки.
Таким образом, он пахнет, как обработчик событий (или, скорее, какой-то метод в стеке) захватывает некоторый глобальный ресурс, который нужен всем другим 32-битным процессам. Поскольку VS2008 - это 32-битный процесс, он должен ждать. Но поскольку существует точка прерывания, мое приложение тоже не запускается, следовательно, тупик. Кроме того, изменение содержимого раскрывающегося списка пытается захватить ту же блокировку, и поэтому в моем приложении возникает тупик. Однако, если заранее есть пауза (когда точка останова дважды удаляется), условие гонки не наступает, и все работает снова.
Но ... я не могу представить, каким мог бы быть этот глобальный ресурс.