Дескриптор SafeHandle был закрыт.
От: Flammable Россия  
Дата: 20.03.11 10:45
Оценка:
Есть приложение на шарпе, использующее "безопасные" дескрипторы следующим образом:


            if (this.InvokeRequired)
            {
                ISetWindowStateCallback = BeginInvoke(pSetWindowState_Show);
                using (ISetWindowStateCallback.AsyncWaitHandle)
                {
                    try
                    { EndInvoke(ISetWindowStateCallback); }
                    catch
                    {  /* Дескриптор закрыт */ }
                }
            }
            else
            {
                this.ShowInTaskbar = true;
            }


У меня все работает хорошо. Но у некоторых других пользователей случается такой вылет:

Дескриптор SafeHandle был закрыт

Boolean SetEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle)
Boolean Set()
Void Complete()
Void InvokeMarshaledCallbacks()
Void WndProc(System.Windows.Forms.Message ByRef)
Void WndProc(System.Windows.Forms.Message ByRef)
Void WndProc(System.Windows.Forms.Message ByRef)
Void WndProc(System.Windows.Forms.Message ByRef)
Void OnMessage(System.Windows.Forms.Message ByRef)
Void WndProc(System.Windows.Forms.Message ByRef)
IntPtr DebuggableCallback(IntPtr, Int32, IntPtr, IntPtr)
IntPtr DispatchMessageW(MSG ByRef)
Boolean System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
Void RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
Void RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
Void Run(System.Windows.Forms.Form)
Void Main(System.String[])


Это может случаться и сразу после запуска, и через некоторое время.
В чем проблема?
Спасибо.
Re: Дескриптор SafeHandle был закрыт.
От: _FRED_ Черногория
Дата: 20.03.11 13:29
Оценка:
Здравствуйте, Flammable, Вы писали:

F>Есть приложение на шарпе, использующее "безопасные" дескрипторы следующим образом:

F>ISetWindowStateCallback = BeginInvoke(pSetWindowState_Show);
F>using (ISetWindowStateCallback.AsyncWaitHandle)


"ISetWindowStateCallback.AsyncWaitHandle" кто создал? Почему вы решили, что имеете право его закрывать?

Разбираться же надо с самим кодом синхронизации, а не тем, как он используется.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Дескриптор SafeHandle был закрыт.
От: Flammable Россия  
Дата: 20.03.11 13:55
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Flammable, Вы писали:


F>>Есть приложение на шарпе, использующее "безопасные" дескрипторы следующим образом:

_FR>
F>>ISetWindowStateCallback = BeginInvoke(pSetWindowState_Show);
F>>using (ISetWindowStateCallback.AsyncWaitHandle)
_FR>


_FR>"ISetWindowStateCallback.AsyncWaitHandle" кто создал? Почему вы решили, что имеете право его закрывать?


_FR>Разбираться же надо с самим кодом синхронизации, а не тем, как он используется.


Ранее я на этом же форуме создавал тему, в которой спрашивал, почему при обработке событий растет количество открытых дескрипторов (по показаниям Диспетчера задач). Предложили использовать такой код.
ISetWindowStateCallback.AsyncWaitHandle, насколько я понимаю, создается методом BeginInvoke. Почему я не имею право его закрывать?
Re[3]: Дескриптор SafeHandle был закрыт.
От: _FRED_ Черногория
Дата: 20.03.11 17:35
Оценка:
Здравствуйте, Flammable, Вы писали:

_FR>>"ISetWindowStateCallback.AsyncWaitHandle" кто создал? Почему вы решили, что имеете право его закрывать?


F>Ранее я на этом же форуме создавал тему, в которой спрашивал, почему при обработке событий растет количество открытых дескрипторов (по показаниям Диспетчера задач). Предложили использовать такой код.


И количество дескрипторов перестало расти?

F>ISetWindowStateCallback.AsyncWaitHandle, насколько я понимаю, создается методом BeginInvoke. Почему я не имею право его закрывать?


Потому что о закрытии должен подумать тот, кто открывает. Посмотри например реализацию этого паттерна здесь. Всё, что обязан сделать вызывающий: выполнить EndInvoke и именно внутри этого метода должны быть освобождены необходимы ресурсы.

_FR>>Разбираться же надо с самим кодом синхронизации, а не тем, как он используется.


Но вы так и не ответили: код в BeginInvoke ваш собственный? Какой-то сторонней библиотеки?
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Дескриптор SafeHandle был закрыт.
От: Аноним  
Дата: 20.03.11 17:45
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Потому что о закрытии должен подумать тот, кто открывает.

Справедливости ради, в примере на МСДН он тоже закрывается в ручную.

Конкретно в этом примере вообще не понимаю зачем обращаться к AsyncWaitHandle(не говоря о том что связку BeginInvoke + EndInvoke проще заменить на Control.Invoke). Но поведение действительно загадочное, если никто больше к AsyncWaitHandle не обращается.
Re: Дескриптор SafeHandle был закрыт.
От: Аноним  
Дата: 20.03.11 17:52
Оценка:
Здравствуйте, Flammable, Вы писали:

   ISetWindowStateCallback = BeginInvoke(pSetWindowState_Show);


ISetWindowStateCallback — локальная переменная или свойство/поле класса? где-нибудь еще в коде есть к нему обращения?
Re[2]: Дескриптор SafeHandle был закрыт.
От: Flammable Россия  
Дата: 20.03.11 18:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Flammable, Вы писали:


А>
А>   ISetWindowStateCallback = BeginInvoke(pSetWindowState_Show);
А>


А>ISetWindowStateCallback — локальная переменная или свойство/поле класса? где-нибудь еще в коде есть к нему обращения?


Это статическое свойство класса. Нашел второе обращение к нему, там он и мог быть закрыт... Код поправил, буду ждать результатов. Спасибо
Re[5]: Дескриптор SafeHandle был закрыт.
От: _FRED_ Черногория
Дата: 20.03.11 18:16
Оценка:
Здравствуйте, Аноним, Вы писали:

_FR>>Потому что о закрытии должен подумать тот, кто открывает.

А>Справедливости ради, в примере на МСДН он тоже закрывается в ручную.

Какое отношение тот пример имеет к рассматриваемому? То, что там и там BeginInvoke? Это всего-навсего паттрен и то, как он работает в той или иной ситуации (с тем или иным объектом), к сожелению, нужно знать. То, что какие-то чудики не смогли сделать всё как полагается, отделавшись этой вот порнографией:

Notes to Callers
Clients that wait for the operation to complete (as opposed to polling) use this property to obtain a synchronization object to wait on.

Note
When you use the BeginInvoke method of a delegate to call a method asynchronously and obtain a wait handle from the resulting IAsyncResult, we recommend that you close the wait handle as soon as you are finished using it, by calling the WaitHandle.Close method. If you simply release all references to the wait handle, system resources are freed when garbage collection reclaims the wait handle, but garbage collection works more efficiently when disposable objects are explicitly closed or disposed. For more information, see the AsyncResult.AsyncWaitHandle property.


"we recommend" понимаешь В BCL, к сожалению, довольно много кривых мест, никуда не денешься. Но это не значит, что их следует повторять. Освобождать ресурс следует на той же стороне, на которой тот и выделяется — только такой подход приводит к переиспользуемому, рефакторабельному, понятному и простому коду.
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.