общих ответы, такие как here и here к огню и забыть вопросов не использовать асинхронный/Await, но использовать Task.Run
или TaskFactory.StartNew
прохождение в синхронном методе вместо ,
Однако иногда метод, который я хочу использовать fire-and-forget, является асинхронным и нет эквивалентного метода синхронизации.и забыть метод асинхронного в ASP.NET MVC
Обновить примечание/предупреждение: Как показано ниже, Стивен Клири, опасно продолжать работу над запросом после того, как вы отправили ответ. Причина в том, что AppDomain может быть закрыт, пока эта работа все еще выполняется. Для получения дополнительной информации см. Ссылку в его ответе. В любом случае, я просто хотел указать на это заранее, чтобы я никого не посылал по неверному пути.
Я думаю, что мой случай действителен, потому что фактическая работа выполняется другой системой (другой компьютер на другом сервере), поэтому мне нужно только знать, что сообщение осталось для этой системы. Если есть исключение, ничего не может сделать сервер или пользователь, и это не влияет на пользователя, все, что мне нужно сделать, это обратиться к журналу исключений и очистить вручную (или реализовать какой-либо автоматизированный механизм). Если AppDomain выключен, у меня будет остаточный файл в удаленной системе, но я выберу это как часть моего обычного цикла обслуживания, и поскольку его существование больше не известно моему веб-серверу (базе данных), и его имя уникально timestamped, он не вызовет никаких проблем, пока он все еще задерживается.
Было бы идеально, если бы у меня был доступ к механизму персистентности, как указал Стивен Клири, но, к сожалению, я этого не делаю в это время.
Я считал, что просто притворяюсь, что запрос DeleteFoo завершился нормально на стороне клиента (javascript), сохраняя запрос открытым, но мне нужна информация в ответе, чтобы продолжить, поэтому он будет держать вещи вверх.
Итак, оригинальный вопрос ...
, например:
//External library
public async Task DeleteFooAsync();
В моем ASP.NET MVC код, который я хочу, чтобы позвонить DeleteFooAsync в огонь и забыл моды - Я не» t хотите сохранить ответ, ожидающий завершения DeleteFooAsync. Если по какой-то причине DeleteFooAsync сработает (или выбрасывает исключение), пользователь или программа не могут ничего сделать, поэтому я просто хочу зарегистрировать ошибку.
Теперь я знаю, что любые исключения приведет к ненаблюдаемых исключений, поэтому простейший случай, я могу думать:
//In my code
Task deleteTask = DeleteFooAsync()
//In my App_Start
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
m_log.Debug("Unobserved exception! This exception would have been unobserved: {0}", e.Exception);
e.SetObserved();
};
Существуют ли какие-либо риски при этом?
Другой вариант, что я могу думать о том, чтобы сделать свою собственную оболочку, такие как:
private void async DeleteFooWrapperAsync()
{
try
{
await DeleteFooAsync();
}
catch(Exception exception)
{
m_log.Error("DeleteFooAsync failed: " + exception.ToString());
}
}
, а затем вызвать, что с TaskFactory.StartNew (вероятно, обертывание в действие асинхронным). Однако это похоже на много кода оболочки каждый раз, когда я хочу вызвать метод async в режиме «огонь и забыть».
Мой вопрос в том, что это правильный способ вызова метода асинхронного использования в режиме «огонь и забыть»?
UPDATE:
Ну, я обнаружил, что следующий в моем контроллере (не то, что действие контроллера должен быть асинхронным, потому что есть другие асинхронные вызовы, долгожданные):
[AcceptVerbs(HttpVerbs.Post)]
public async Task<JsonResult> DeleteItemAsync()
{
Task deleteTask = DeleteFooAsync();
...
}
вызвало исключение:
Unhandled Exception: System.NullReferenceException: Ссылка на объект not s et к экземпляру объекта. на System.Web.ThreadContext.AssociateWithCurrentThread (BooleansetImpersonationContext)
Это обсуждается here и кажется, что делать с SynchronizationContext и «возвращенной задачей было перешли на терминальное состояние, прежде чем вся асинхронную работа завершена.
Таким образом, единственный метод, который работал был:
Task foo = Task.Run(() => DeleteFooAsync());
Мое понимание того, почему это работает, потому что StartNew получает новую нить для DeleteFooAsync работать.
К сожалению, предложение Скотта ниже не работает для обработки исключений в этом случае, поскольку foo больше не является задачей DeleteFooAsync, а скорее задачей Task.Run, поэтому не обрабатывает исключения из DeleteFooAsync. Мое UnobservedTaskException в конечном итоге вызвано, поэтому по крайней мере это все еще работает.
Итак, я догадываюсь, что вопрос по-прежнему стоит, как вы стреляете и забываете метод async в asp.net mvc?
возможно дубликат [Как обрабатывать ненаблюдаемые исключений в ASP.NET MVC] (http://stackoverflow.com/questions/18501919/how-to-handle-unobserved-exceptions -in-asp-net-mvc) –
lol. Это еще один вопрос, который я задал. Этот вопрос касается того, как обрабатывать незаметные исключения. Этот вопрос касается того, как делать вызовы метода «огонь и забухание», когда метод «огонь и забухание» является асинхронным. – acarlon
Вы должны использовать 'Task.Run' вместо' TaskFactory.StartNew' в коде 'async' (http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx) , –