Я сожалею, что в рамках контракта IDisposable
Microsoft не требовала, чтобы реализации позволяли вызывать Dispose
из любого контекста потоков, так как не существует нормального способа, которым создание объекта может привести к продолжению существование контекста потоков, в котором он был создан. Можно спроектировать код так, чтобы поток, который создает объект, каким-то образом наблюдал, как объект устарел, и может Dispose
по своему удобству, и чтобы когда поток больше не нужен ни для чего другого, он оставался до тех пор, пока все не станет подходящим. объекты были Dispose
d, но я не думаю, что есть стандартный механизм, который не требует специального поведения со стороны потока, создающего Dispose
.
Ваша лучшая ставка, вероятно, состоит в том, чтобы все объекты, представляющие интерес, создавались в общем потоке (возможно, в потоке пользовательского интерфейса), пытаться гарантировать, что поток будет оставаться в течение всей жизни объектов, представляющих интерес, и использовать что-то вроде Control.BeginInvoke
запросить распоряжение объектами. При условии, что ни создание объекта, ни очистка не будут блокироваться в течение любого промежутка времени, это может быть хорошим подходом, но если любая операция может заблокировать другой подход, может потребоваться другой подход [возможно, откройте скрытую фиктивную форму со своим собственным потоком, так что можно используйте Control.BeginInvoke
там].
В качестве альтернативы, если у вас есть контроль над реализациями IDisposable
, спроектируйте их так, чтобы они могли безопасно запускаться асинхронно. Во многих случаях это будет «просто работать» при условии, что никто не пытается использовать предмет, когда он утилизируется, но это вряд ли является данностью. В частности, для многих типов IDisposable
существует реальная опасность того, что несколько экземпляров объекта могут манипулировать общим внешним ресурсом [например, объект может содержать List<>
созданных экземпляров, добавлять экземпляры в этот список при их создании и удалять экземпляры в Dispose
; если операции со списком не синхронизированы, асинхронный Dispose
может повредить список, даже если располагаемый объект не используется иным образом.
Кстати, полезный шаблон - объекты, позволяющие асинхронное удаление во время их использования, с ожиданием, что такое удаление приведет к тому, что любые выполняющиеся операции вызовут исключение при первой удобной возможности. Такие вещи, как сокеты, работают таким образом. Для операции чтения может быть невозможным преждевременное завершение операции, не оставляя свой сокет в бесполезном состоянии, но если сокет никогда не будет использоваться в любом случае, нет смысла для чтения продолжать ждать данных, если другой поток определил, что это должно сдаться. ИМХО, именно так все IDisposable
объекты должны стараться вести себя, но я не знаю ни одного документа, призывающего к такой общей схеме.