как правильно создать исключение ожидаемого метода - PullRequest
0 голосов
/ 29 мая 2018

Я потратил часы, пытаясь понять это (название).Итак, у меня есть два метода:

public virtual TEntity GetByName(Expression<Func<TEntity, bool>> whereName)
    {
        return this.DbEntitySet.FirstOrDefault(whereName);;
    } 

и

public virtual async Task<TEntity> GetByNameAsync(Expression<Func<TEntity, bool>> whereName)
    {
        try
        {                
            return await this.DbEntitySet.FirstOrDefaultAsync(whereName);
        }
        catch (AggregateException ae)
        {
            throw;
        }
        catch (Exception ex)
        {

            throw;
        }
    }  

первый метод работает, как ожидалось, но второй работает нормально, если он найден, но входит в бесконечный процесс, если онне.Я ожидаю, что будет сгенерировано исключение (возможно, через AggregateException), даже если оно не генерирует исключение TimeOutException.Я попытался изменить его, как:

public virtual async Task<TEntity> GetByNameAsync(Expression<Func<TEntity, bool>> whereName)
    {
        try
        {
            TimeSpan ts = TimeSpan.FromMilliseconds(5000);
            Task<TEntity> task = this.DbEntitySet.FirstOrDefaultAsync(whereName);
            if (!task.Wait(ts))
            {
                throw new TimeoutException();
            }
            return await task;
        }
        catch (AggregateException ae)
        {
            throw;
        }
        catch (Exception ex)
        {

            throw;
        }
    }

, а затем этот метод работает нормально WITHOUT ANY exception.Любая помощь, пожалуйста ??

Вот как я называю этот метод (с начала)

//1
var activityManager = HttpContext.Current.GetOwinContext().Get<ActivityManager<ActivityModels>>();
activityManager.CreateAsync(model).GetAwaiter().GetResult();
//2
public virtual async Task<WebCoreResult> CreateAsync(TActivity activity)
    {
        this.ThrowIfDisposed();

        if ((object)activity == null || string.IsNullOrEmpty(activity.ActivityName))
            throw new ArgumentNullException(nameof(activity));
        try
        {

            WebCoreResult result = await ActivityExistAsync(activity);
            if (result.Succeeded)
                return result;
        }
        catch (Exception)
        {

            throw;
        }
        //code removed for brevity                
    }
//3
public async Task<WebCoreResult> ActivityExistAsync(TActivity activity)
    {
        var a = await FindByNameAsync(activity.ActivityName);
        //var a = FindByName(activity.ActivityName);    //this one ok

        if (a == null)
        {
            return await Task.FromResult(new WebCoreResult("Activity not exist"));
        }
        return await Task.FromResult(WebCoreResult.Success);
    }
//4
public virtual async Task<TActivity> FindByNameAsync(string activityName)
    {
        this.ThrowIfDisposed();
        if (activityName == null)
            throw new ArgumentNullException(nameof(activityName));
        return (TActivity)await this._activityStore.FindByNameAsync(activityName);
    }
//5
public async Task<ActivityModels> FindByNameAsync(string name)
    {
        this.ThrowIfDisposed();
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentNullException("activityname");
        }
        return await _activityStore.GetByNameAsync(x => x.ActivityName.ToLower() == name.ToLower());
    }
//6 finale: GetByNameAsync method above

1 Ответ

0 голосов
/ 29 мая 2018

Вероятно, проблема вызвана этой строкой:

activityManager.CreateAsync(model).GetAwaiter().GetResult()

Вызов GetResult заставляет поток блокироваться до завершения Awaiter.Таким образом, вы блокируете основной цикл ASP.NET.Проблема теперь возникает, как только один await пытается продолжить выполнение.На этом этапе он запланирует продолжение в SynchronizationContext, которое подключено к основному потоку ASP.NET.Но это продолжение никогда не выполняется, потому что поток заблокирован как GetResult.

И именно так вы, вероятно, создали тупик.

Есть несколько способов, как это исправить.

  1. Не смешивайте await с Wait() и GetResult().Если вы используете только один из них, у вас все будет в порядке.
  2. Если вам нужно заблокировать поток с вероятностью SynchronizationContext, вам нужно убедиться, что функции, использующие await, не являютсяпытаясь восстановить этот контекст.Самый простой способ сделать это - заключить начальный вызов в Task.Run(() => ...).Это будет работать.Вы можете узнать, есть ли SynchronizationContext в текущем активном потоке, запросив System.Threading.SynchronizationContext.Current.Если это null или экземпляр System.Threading.SynchronizationContext у вас все в порядке.Если это какая-то специальная реализация, вам нужно остерегаться.
  3. Вам нужно заказать await вызовы, чтобы игнорировать текущий SynchronizationContext.Это можно сделать, вызвав ConfigureAwait(false) на ожидаемых объектах.Но вы должны делать это, по крайней мере, на каждом первом await в каждом задействованном методе.

Любой из этих способов решит проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...