Как я могу вызвать метод асинхронного действия с помощью Hangfire

Я работаю над веб-приложением asp.net mvc5 и установил Hangfire: -

Install-Package Hangfire

после этого я создал класс startup.css следующим образом: -

public class Startup
{
   public void Configuration(IAppBuilder app)
   {

   }
}

затем внутри моего файла global.asax я попытался вызвать 2 метода действий; Index () и ScanServer() следующим образом: -

 HomeController h = new HomeController();
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);


            RecurringJob.AddOrUpdate(() =>  h.Index(), Cron.Minutely);
        }

&

 RecurringJob.AddOrUpdate(() =>  h.ScanServer(*****), Cron.Minutely);

теперь, когда Hangfire попытался вызвать метод действия Index(), который имеет следующее определение: -

 public ActionResult Index()

я получил эту ошибку: -

Значение свойства JobStorage.Current не было инициализировано. Вы должны установить его перед использованием Hangfire Client или Server API.

в то время как когда Hangfire пытался вызвать метод действия ScanServer(), который является асинхронной задачей, которая имеет следующее определение: -

 public async Task<ActionResult> ScanServer(string tokenfrom)

я получил эту ошибку: -

Асинхронные методы не поддерживаются. Пожалуйста, сделайте их синхронными, прежде чем использовать их в фоновом режиме.

так может ли кто-нибудь посоветовать, как исправить эти 2 проблемы?

Спасибо

ИЗМЕНИТЬ

я написал следующее внутри класса Startup: -

using Hangfire;
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ScanningFinal;
[assembly: OwinStartup(typeof(Startup))]
namespace ScanningFinal
{

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configuration
           .UseSqlServerStorage("scanservice");
        }
    }
}

& вот строка подключения: -

 <add name="scanservice"    connectionString="data source=localhost;initial catalog=ScanningService;integrated security=True" providerName="System.Data.SqlClient"/>

но я все еще получаю эту ошибку: -

Значение свойства JobStorage.Current не было инициализировано. Вы должны установить его перед использованием Hangfire Client или Server API.


person john Gu    schedule 10.09.2015    source источник
comment
Вы оставили метод конфигурации пустым в классе Startup?   -  person Tom    schedule 10.09.2015
comment
@mason, но могу ли я заставить его хранить задания, например, в текстовом файле? или это должна быть БД?   -  person john Gu    schedule 10.09.2015
comment
@ Том, да, я оставил их пустыми, хотя они мне нужны, если я хочу получить доступ к панели инструментов? и вызывает ли это проблему для вызова метода асинхронного действия?   -  person john Gu    schedule 10.09.2015
comment
Вам нужен какой-то механизм хранения заданий. На самом деле неважно, какой сорт. Но дело в том, что мне не известно встроенного поставщика хранилища заданий для текстовых файлов. Так что вам придется реализовать это самостоятельно, что является большой задачей. Вам лучше использовать один из существующих механизмов хранения. Мне было легко настроить и использовать MongoDB, возможно, она удовлетворит и ваши потребности. Или, если у вас есть существующая база данных SQL Server, это тоже сработает.   -  person mason    schedule 10.09.2015
comment
да, у меня есть SQL-сервер, и моя текущая система использует его, но я не хочу, чтобы Hangfire использовал ту же базу данных, что и моя система, поэтому я могу создать новую базу данных специально для Hangfire и определить для нее строку подключения внутри запуск.config ?   -  person john Gu    schedule 10.09.2015
comment
@johnG Да, можешь :)   -  person Tom    schedule 10.09.2015
comment
@Tom, но это может не работать из-за разрешений. теперь пользователь пула приложений может только читать и писать в базу данных, но не может создавать новые таблицы....   -  person john Gu    schedule 10.09.2015
comment
@johnG Коду не место в комментариях. Поместите это в свой вопрос.   -  person mason    schedule 10.09.2015
comment
@mason, не могли бы вы проверить мое редактирование, я предоставил код ..   -  person john Gu    schedule 10.09.2015
comment
Есть два места, где вы можете настроить хранилище заданий, в зависимости от того, используете ли вы OWIN или нет. Прочтите документацию. Попробуйте переместить конфигурацию хранилища заданий в Application_Start выше, где вы добавляете само задание.   -  person mason    schedule 10.09.2015
comment
но я использую asp.net mvc5, и да, я использую owin.. поэтому я выбрал второй подход..   -  person john Gu    schedule 10.09.2015
comment
Затем переместите RecurringJob.AddOrUpdate(() => h.Index(), Cron.Minutely); в метод запуска OWIN. Не размещайте их в разных местах.   -  person mason    schedule 10.09.2015
comment
Хорошо, это сработало хорошо, и таблицы были созданы правильно, но я не уверен, что у меня возникнут проблемы в моей живой среде из-за отсутствия разрешения на создание таблиц.   -  person john Gu    schedule 10.09.2015
comment
@johnG Просто дайте учетной записи, с которой она работает, правильные разрешения.   -  person mason    schedule 10.09.2015
comment
но из-за ограничений безопасности и пула приложений не будет разрешено создавать новые таблицы ... так что, если я создам таблицу вручную, это сработает? и будет ли их использовать Hangfire?   -  person john Gu    schedule 10.09.2015
comment
Как Hangfire узнает, создал ли он их или что-то другое? Это не так. Так что, если у вас есть скрипты для настройки БД, то дерзайте.   -  person mason    schedule 10.09.2015


Ответы (1)


Вам необходимо настроить Hangfire в рамках вашего метода конфигурации.

[assembly: OwinStartup(typeof(YourApp.Startup))] // Change YourApp to your base namespace
public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseHangfire(config => 
        {
            config.UseSqlServerStorage("NameOfConnectionStringKey"); // Other storage options are available
            config.UseDashboardPath("/hangfire");
            config.UseServer();
        });
    }
}

По сути, ваша первая проблема заключается в том, что вы не настроили Hangfire для использования базы данных. В приведенном выше решении я говорю Hangfire использовать SqlServer в качестве хранилища заданий, передавая ему ключ connectionString, определенный в файле web.config. Если вы не хотите использовать SQL Server, вы можете использовать другие варианты хранения — я успешно использовал MongoDB в своих проектах.

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

Вы также можете указать здесь выбранную вами инъекцию зависимостей.

Что касается вашего второго вопроса, можете ли вы изменить метод обслуживания с асинхронного на синхронный?

person Tom    schedule 10.09.2015
comment
да, я могу изменить свою службу с асинхронной на синхронную, но я не хочу этого делать? так как я хочу, чтобы метод действия был асинхронным методом действия... - person john Gu; 10.09.2015
comment
Я почти уверен, что Hangfire в любом случае будет выполнять операцию асинхронно, так что я бы не слишком беспокоился об этом. - person Tom; 10.09.2015
comment
но мне нужно, чтобы метод действия был асинхронным, потому что один и тот же метод действия может быть вызван вручную конечными пользователями.. поэтому в этом случае мне нужно создать другую версию метода действия.. которая не будет очень надежной... я имею в виду, что в конечном итоге у меня будет две версии асинхронного и синхронного метода действия !!! можешь посоветовать? - person john Gu; 10.09.2015
comment
@johnG Зачем вам нужен еще один метод действия? Почему бы не использовать метод, который вызывает метод ожидания задачи? - person mason; 10.09.2015
comment
@mason, можешь посоветовать по этому поводу больше, пожалуйста? не уверен, что я понял вашу точку зрения? теперь мне нужно асинхронное действие, потому что пользователи могут вызывать асинхронный метод вручную из своих браузеров, а Hangfire не позволяет вызывать асинхронный метод действия. Можете ли вы посоветовать больше по вашему предложению? - person john Gu; 10.09.2015
comment
Методы асинхронного действия @johnG возвращают задачу. Эта задача имеет функцию Wait. Вы можете вызывать это из синхронного кода, таким образом, используя ваш метод асинхронного действия синхронным образом, удовлетворяя Hangfire. - person mason; 10.09.2015
comment
поэтому вы хотите написать еще один метод действия следующим образом: вернуть Контент (завершено); } - person john Gu; 10.09.2015
comment
@johnG Нет, вам не нужен метод действия. Просто вызовите функцию .Wait() задачи, которую возвращает ваш метод асинхронного действия. - person mason; 10.09.2015
comment
Давайте продолжим обсуждение в чате. - person john Gu; 10.09.2015
comment
@mason, вы хотите написать следующее: RecurringJob.AddOrUpdate(() => h.ScanServer(****).Wait(), Cron.Minutely); - person john Gu; 10.09.2015
comment
@mason также я заметил кое-что теперь, когда я впервые запустил свое приложение в Visual Studio, ScanServer был вызван, но он никогда не вызывался снова, хотя я определяю его для запуска каждую минуту ... пожалуйста, не говорите мне, что Hangfire не сработает, если нет есть какая-то активность сервера? - person john Gu; 10.09.2015
comment
@johnG Да, я имею в виду это. Hangfire может работать только тогда, когда запущено приложение. Поэтому, если вам нужно запускать его постоянно, прочитайте инструкции, как это сделать. Вы можете проверить панель инструментов, чтобы увидеть, когда она выполняется. - person mason; 10.09.2015
comment
@mason кажется, что много настроек, есть ли другой способ заставить Hangfire выполняться, даже если в приложении нет активности? - person john Gu; 11.09.2015
comment
@johng подумай об этом. Как может выполняться Hangfire, если приложение, в котором оно размещено, даже не запущено? - person mason; 11.09.2015
comment
@mason, но что ты имеешь в виду, говоря, что хостинг приложений не работает? теперь, если я попытаюсь войти в приложение после 2 дней бездействия, я смогу, поэтому приложение будет работать,, это правильно? неактивность приложения отличается от того, что приложение не запущено, правильно ли это? или я вас не так понял.. - person john Gu; 11.09.2015
comment
@johnG Когда дело доходит до ASP.NET, часто бездействие означает, что приложение буквально останавливается. Если вы используете IIS локально, вам нужно следовать указаниям, на которые я ссылался выше, чтобы заставить Hangfire работать постоянно. Или, если вы размещаете в Azure платный экземпляр, вы можете просто настроить его на автозапуск. Но обычно после определенного периода бездействия (обычно 20 минут) IIS выгружает приложение, поэтому Hangfire не сможет выполниться. - person mason; 11.09.2015
comment
@mason да, в моем случае я использую IIS локально - person john Gu; 11.09.2015
comment
@johnG Тогда вы можете следовать указаниям, на которые я ссылался выше. - person mason; 11.09.2015
comment
@mason большое спасибо за помощь. Теперь я собираюсь использовать IIS 7 с Windows 2008 R2, будут ли работать эти шаги? как упоминалось, что эти шаги применимы к IIS 7.5 или выше? - person john Gu; 11.09.2015
comment
@johnG Пожалуйста, прочитайте инструкции, так как в них конкретно указано, какая версия IIS поставляется с Windows 2008 R2. - person mason; 11.09.2015
comment
хорошо, в указании говорится следующее: вы можете использовать функцию автозапуска IIS ≥ 7.5, поставляемую с Windows Server ≥ 2008 R2, поэтому в моем случае у меня есть IIS 7.0, значит ли это, что я не могу работать с Hangefire? ?? - person john Gu; 11.09.2015