Недавно мы приняли TPL в качестве инструментария для выполнения некоторых сложных фоновых задач.
Эти задачи обычно создают один объект, который реализует IDisposable
.Это потому, что у него есть некоторые операционные системы внутри.
Я хочу, чтобы объект, созданный фоновым потоком, всегда был правильно расположен, даже когда передача обслуживания совпадает с завершением работы приложения.
Подумав, я написал:
private void RunOnUiThread(Object data, Action<Object> action)
{
var t = Task.Factory.StartNew(action, data, CancellationToken.None, TaskCreationOptions.None, _uiThreadScheduler);
t.ContinueWith(delegate(Task task)
{
if (!task.IsCompleted)
{
DisposableObject.DisposeObject(task.AsyncState);
}
});
}
Фон Task
вызывает RunOnUiThread
для передачи своего результата в поток пользовательского интерфейса.Задача t
запланирована в потоке пользовательского интерфейса и становится владельцем переданного data
. Я ожидал, что если t
не удастся выполнить из-за того, что насос сообщений потока пользовательского интерфейса был отключен, продолжение продолжится,и я мог видеть, что задание не выполнено, и сам распоряжался объектом.DisposeObject()
- это помощник, который проверяет, является ли объект действительно идентифицируемым и ненулевым, перед его удалением.
К сожалению, это не работает.Если я закрою приложение после создания фоновой задачи t
, продолжение не будет выполнено.
Я решил эту проблему раньше.В то время я использовал Threadpool и диспетчер WPF для публикации сообщений в потоке пользовательского интерфейса.Это было не очень красиво, но в конце концов это сработало.Я надеялся, что TPL был лучше в этом сценарии.Было бы даже лучше, если бы я мог как-то научить TPL, что он должен утилизировать все оставшиеся объекты AsyncState, если они реализуют IDisposable.
Итак, код предназначен в основном для иллюстрации проблемы.Я хочу узнать о любом решении, которое позволяет мне безопасно передавать одноразовые объекты потоку пользовательского интерфейса из фоновых задач, и желательно с минимальным количеством кода.