Страницы

Поиск по вопросам

понедельник, 13 мая 2019 г.

Класс устанавливающий курсор ожидания и автоматически сбрасывающий его

Создал вот такой класс:
class CursorEx: IDisposable { public CursorEx() { Cursor.Current = Cursors.WaitCursor; } public void Dispose() { Cursor.Current = Cursors.Default; } }
Использую вот так:
public void Method() { new CursorEx(); //Здаесь что-то выполняется }
Подразумевается, что после выполнения метода, вызовется метод Dispose() и курсор установится на дефолтный. Могут ли быть какие-то варианты, когда произойдет сбой?


Ответ

Во-первых, вы забыли вызвать Dispose. Для этого следует использовать using
using (new CursorEx()) { // что-то выполняется }
На сборку мусора полагаться нельзя, она вызывается недетерминированно в любой момент после пропадания объекта из области видимости.
Во-вторых, вы не восстанавливаете исходный курсор. Если какая-то функция изменяет курсор, а затем вызывает функцию, которая тоже изменяет курсор, то курсор будет восстановлен уже после возврата из первой функции:
using (new CursorEx()) { using (new CursorEx()) { // что-то выполняется } // курсор уже восстановлен } // курсор должен был быть восстановлен здесь
Вам следует сохранять текущий курсор в конструкторе и восстанавливать его в Dispose
В-третьих, можно избавиться от лишнего объекта в памяти, если заменить класс на структуру.
Итого:
public struct CursorWaiter : IDisposable { private readonly Cursor _originalCursor;
public CursorWaiter (Cursor newCursor = null) { _originalCursor = Cursor.Current; Cursor.Current = newCursor ?? Cursors.WaitCursor; }
public void Dispose () { Cursor.Current = _originalCursor; } }
Из комментариев: этот код рассчитан на то, что программист будет использовать тип только с помощью using, не будет уничтожать объект по несколько раз, не будет копировать и т.п. Если есть сомнения в этом, то нужно добавить проверку на повторный вызов Dispose (с помощью отдельного флага или обнуления _originalCursor), а также заменить класс на структуру для избавления он возможности копирования или вовсе скрыть тип за методом с лямбдой.

Комментариев нет:

Отправить комментарий