C # — возвращает IEnumerable при асинхронном вызове задачи

#c# #asynchronous #task

#c# #асинхронный #задача

Вопрос:

У меня есть следующий код:

 public class TardiisServiceAsync
{
    private static TardiisServiceAsync instance;

    public static TardiisServiceAsync Instance
    {
        //Singleton
        get
        {
            if (instance == null)
            {
                instance = new TardiisServiceAsync();
            }
            return instance;
        }
    }
    public const string CACHE_PREFIX_TARDIIS_SERVICE = "TardiisServiceAsync_";
    public static Dictionary<string, Tuple<string, object>> clients = new Dictionary<string, Tuple<string, object>>();
    public delegate Task<IEnumerable<object>> GetServiceList(object client, string connectionId, TardiisServiceParameters parameters = null);


    public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
    {
        //Returns IEnumerable<object> task
        var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
        var result = await test;
        return (IEnumerable<object>)resu<
    }

    public async Task<IdNameObject[]> GetDemographicGroupsAsync()
    {
        //This task is called from hight level class
        Task<IdNameObject[]> cacheValue = null;
        string cacheKey = CACHE_PREFIX_TARDIIS_SERVICE   Membership.GetUser().UserName   "GetDemographicGroupsAsync"   GetMarketCode();

        if (ConfigurationManager.AppSettings[ConstantsHelper.FIELD_CONFIG_USE_CACHE_KEY] != null amp;amp; bool.Parse(ConfigurationManager.AppSettings[ConstantsHelper.FIELD_CONFIG_USE_CACHE_KEY]))
        {
            if (HttpContext.Current.Cache[cacheKey] == null)
            {
                var taskResult = InitializeTardiisInstanceAndCallService(GetDemographicGroupsDelegateAsync);
                var test = await taskResu<
                cacheValue = (Task<IdNameObject[]>)HttpContext.Current.Cache[cacheKey];//This is not implemented yet
            } 
        }

        return await cacheValue;
    }

    public static Task<T> Convert<T>(T value)
    {
        return Task.FromResult<T>(value);
    }

    public static EnumHelper.EnumMarketCode GetMarketCode(EnumHelper.EnumMarketCode? marketCode = null)
    {
        //Returns market code
        if (!marketCode.HasValue)
            return (EnumHelper.EnumMarketCode.US);
        else
            return marketCode.Value;
    }

    private Task<IEnumerable<object>> InitializeTardiisInstanceAndCallService(GetServiceList getServiceList, TardiisServiceParameters parameters = null, EnumHelper.EnumMarketCode? marketCode = null, bool creatingConnectionsForAllCountries = false, string username = "")
    {
        //Get the instance and call the tardiis correct tardiis service depends on the market code
        marketCode = GetMarketCode(marketCode);
        MembershipUser membershipUser = Membership.GetUser();
        string currentUsername = (membershipUser != null ? membershipUser.UserName : username);
        string currentKey = currentUsername   "_"   marketCode;

        if (clients.ContainsKey(currentKey))
        {
            try
            {
                //check if the connection is still active, or we should reconnect.
                return getServiceList(clients[currentKey].Item2, clients[currentKey].Item1, parameters);
            }
            catch (Exception) { }
        }
        //At this point there is no connection, we need to open it.                            
        object client = TardiisServiceFactory.GetService(marketCode.Value);

        UserDTO userDTO = UserService.Instance.GetByUsername(currentUsername);
        TardiisUserDTO tardiisUserDTO = UserService.Instance.GetTardiisUserByUserIdAndMarketCode(userDTO.ID, marketCode.Value.ToString());

        if (tardiisUserDTO.TardiisUsername == null)
        {
            if (creatingConnectionsForAllCountries)
                return null;
            else
                throw new TardiisLoginException("Please enter your credentials");
        }

        object user = TardiisServiceFactory.GetUser(marketCode.Value, tardiisUserDTO.TardiisUsername, tardiisUserDTO.TardiisPassword);
        string connectionId;
        try
        {
            connectionId = (string)client.GetType().GetMethod("InitConnection").Invoke(client, new object[] { user });
        }
        catch (FaultException ex)
        {
            // This exception is catched globally by BaseController and prompts the user to enter his
            // tardiis credentials again
            throw new TardiisLoginException(ex.InnerException.Message, ex);
        }
        catch (TargetInvocationException ex)
        {
            // This exception is catched globally by BaseController and prompts the user to enter his
            // tardiis credentials again
            throw new TardiisLoginException(ex.InnerException.Message, ex);
        }

        clients[currentKey] = new Tuple<string, object>(connectionId, client);
        return getServiceList(clients[currentKey].Item2, clients[currentKey].Item1, parameters);
    }

    private void AddToCache(string key, object value)
    {
        HttpContext.Current.Cache.Add(key, value, null, DateTime.Now.AddMinutes(30), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
    }

}
  

Я получаю следующее сообщение об ошибке:

Не удается привести объект типа ‘System.Многопоточность.Задачи.Задача [Система.Объект] для ввода ‘System.Коллекции.Общий.IEnumerable1[Система.Объект].

Результатом задачи является TypedClass[] .

Как я могу вернуть как Task<IEnumerable<object>> при методе вызова.

Это «копия» другого класса, который имеет аналогичную логику, но синхронизированным образом. Идея в том, чтобы изменить некоторые методы, чтобы их можно было запускать синхронно.

Спасибо!

Комментарии:

1. var TaskResult = task.Resu< это не задача, когда вы добавляете .result, это будет перечислимый или другой тип, который вы используете

2. Привет @Pliskin, спасибо за ваш ответ, я понимаю это, но я не могу преобразовать Task<MyCustomClass> результат в Task<IEnumerable<object>> . Спасибо.

3. каков тип TaskResult и тип параметра метода convert?

4. Результатом является Task<TardiisPlanning.TardiisPlanningService.DemographicGroup[]> массив пользовательского класса. Ниже я оставляю код метода Convert: public static Task<T> Convert<T>(T value) { return Task.FromResult<T>(value); }

5. Проверьте обновленный код и дайте мне знать, работает ли он, или добавьте это как параметр Convert resultado. ToList()

Ответ №1:

     public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
{

    var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
    var result = await test;
    var resultado = test.Resu<
    return Convert(new List<Object>{resultado});
}
  

Ответ №2:

Если у вас есть IEnumerable<A> подобный массив, вы можете преобразовать его в IEnumerable<object> , используя Linq-метод Cast<object>()

 public async Task<IEnumerable<object>> GetDemographicGroupsDelegateAsync(object client, string connectionId, TardiisServiceParameters parameters = null)
{

    var test = Convert(client.GetType().GetMethod("GetDemographicGroupsAsync").Invoke(client, new object[] { connectionId }));
    var task = await test;
    var taskResult = await task;
    return taskResult.Cast<object>();
}
  

Комментарии:

1. Привет, Ackdari, спасибо, но переменная taskResullt является типом объекта и не является awatiable, я прав?.

2. @MarceloArias ну, я не знаю, каковы типы ваших объектов? Возможно, я смогу прояснить свой ответ, если вы скажете мне, что такое тип test и что такое тип task .