Должна ли моя библиотека реализовывать как IDisposable, так и IAsyncDisposable? - PullRequest
3 голосов
/ 09 июля 2020

уже есть аналогичный вопрос по этому поводу , но мой вопрос касается класса, доступного для клиента.

public class MyClass : IAsyncDisposable {
  public ValueTask DisposeAsync() => DoAsyncStuff();
}

Удаление этого класса асинхронно и реализация IDisposable заблокирует поток.

public void Dispose() => DisposeAsync().GetAwaiter().GetResult();

Если IDisposable реализовано в классе, а пользователь находится в синхронном контексте, поэтому они используют оператор using: using (var c = new MyClass()) {}, который заблокирует нить в спину пользователя, и я думаю, что это очень плохо. Вместо этого я бы предпочел не реализовывать IDisposable и заставлять пользователя использовать эту явную форму:

MyClass c;
try { c = new MyClass(); }
finally { c.DisposeAsync().GetAwaiter().GetResult(); }

Это более подробно, но, по крайней мере, для пользователя не будет неприятного сюрприза.

Я не включил образец кода своей библиотеки, потому что это общий вопрос. Итак, что вы думаете об этом и испытывали ли вы когда-нибудь проблемы, когда метод Dispose синхронно ждал на Task за вашей спиной?

1 Ответ

5 голосов
/ 09 июля 2020

Ваши аргументы разумны, и в этом сценарии: да, я бы реализовал только IAsyncDisposable.

Что касается вызывающих в контексте syn c: даже эту явную форму следует активно обескураживать. Реальность такова, что asyn c заразителен, и вполне нормально, что код, касающийся компонентов asyn c, также должен быть asyn c. Поэтому принуждение вызывающего абонента к использованию асинхронного c контекста вполне разумно, ИМО.

...