Open Closed

CancellationToken not workin on AppService with blazor project. #1632


User avatar
0
drenton created
  • ABP Framework version: v4.3.3
  • UI type: Blazor
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace:
  • Steps to reproduce the issue:"

Hi there,

I'm trying to use CancellationToken for long running task, I cannot make it work in AppService. but it works well on my local api calls.

protected override async Task OnInitializedAsync()
{
    cts.CancelAfter(2000);//To test CancellationToken
    //Below cancellation work well. 
    //forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("https://localhost:44320/WeatherForecast/", cts.Token);
    
    //This does not work.
    var pageResult = await CallsAppService.GetListAsync(new GetCallsInput { }, cts.Token);
    Calls = pageResult.Items;
}

This is my GetListAsync from CallsAppService

public virtual async Task<PagedResultDto<CallDto>> GetListAsync(GetCallsInput input, CancellationToken ct = default)
{
    Thread.Sleep(3000);//On purpose to test CancellationToken
    var totalCount = await _callRepository.GetCountAsync(input.FilterText, input.Number, ct);
    var items = await _callRepository.GetListAsync(input.FilterText, input.Number, input.Sorting, input.MaxResultCount, input.SkipCount, ct);

    return new PagedResultDto<CallDto>
    {
        TotalCount = totalCount,
        Items = ObjectMapper.Map<List<Call>, List<CallDto>>(items)
    };
}

This is my CallController

[HttpGet]
public virtual Task<PagedResultDto<CallDto>> GetListAsync(GetCallsInput input, CancellationToken ct = default)
{
    return _callsAppService.GetListAsync(input, ct);
}

5 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Currently ABP does not support custom cancellationToken.

    We have create an issue to enhance: https://github.com/abpframework/abp/issues/9668

  • User Avatar
    0
    drenton created

    Hi @liangshiwei

    I tried to use the provier too, but it does not work either. [It seems it just catches the same token, so I don't have to provide it in all the method]

    Can you give me an example that show how to cancel a task from blazor razor view?

    Thanks.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    As I said, currently ABP does not support custom cancellationToken. because the request proxy interceptor always uses the ICancellationTokenProvider.

    This PR will solve the issue, but 5.0.0 version, for now, you can implement it locally.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    HI,

    This is a temporary solution:

    public class CancellationTokenOverride
    {
        public CancellationToken CancellationToken { get; }
    
        public CancellationTokenOverride(CancellationToken cancellationToken)
        {
            CancellationToken = cancellationToken;
        }
    }
    
    
    [Dependency(ReplaceServices = true)]
    public class MyCancellationTokenProvider : ICancellationTokenProvider, ITransientDependency
    {
    
        public const string CancellationTokenOverrideContextKey = "Volo.Abp.Threading.CancellationToken.Override";
    
        public CancellationToken Token { get
        {
            if (OverrideValue != null)
            {
                return OverrideValue.CancellationToken;
            }
            return _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None;
        }}
    
        private readonly IAmbientScopeProvider<CancellationTokenOverride> _cancellationTokenOverrideScopeProvider;
        private readonly IHttpContextAccessor _httpContextAccessor;
        protected CancellationTokenOverride OverrideValue => _cancellationTokenOverrideScopeProvider.GetValue(CancellationTokenOverrideContextKey);
    
        public MyCancellationTokenProvider(
            IAmbientScopeProvider<CancellationTokenOverride> cancellationTokenOverrideScopeProvider,
            IHttpContextAccessor httpContextAccessor)
        {
            _cancellationTokenOverrideScopeProvider = cancellationTokenOverrideScopeProvider;
            _httpContextAccessor = httpContextAccessor;
        }
    
        public IDisposable Use(CancellationToken cancellationToken)
        {
            return _cancellationTokenOverrideScopeProvider.BeginScope(CancellationTokenOverrideContextKey, new CancellationTokenOverride(cancellationToken));
        }
    }
    
    protected override async Task OnInitializedAsync()
    {
        cts.CancelAfter(2000);//To test CancellationToken
        
        using (((MyCancellationTokenProvider) _cancellationTokenProvider).Use(cts.Token))
        {
           var pageResult = await CallsAppService.GetListAsync(new GetCallsInput { });
           Calls = pageResult.Items;
        }
    }
    
  • User Avatar
    0
    drenton created

    Thanks @liangshiwei

    That works wel ;)

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11