简体   繁体   中英

What to use as asyncState object (or where to get it from) in StackExchange.Redis in C#

I try to convert a synchronous redis store to an asynchronous implementation for a .NET Core 2.2 web api using the StackExchange.Redis nuget.

The synchronous version works.

TheBasic Usage Guide states:

Additionally, if you plan to make use of the asynchronous API and you require the Task.AsyncState to have a value, this can also be specified:

int databaseNumber = ...
object asyncState = ...
IDatabase db = redis.GetDatabase(databaseNumber, asyncState);

I am not sure if the statement means I have to set it if I want to use the asnychronous API or I can set it and get some benefit of doing so. If the later what would that benefits be?


The following is my current (simplified) code and I don't know if/when to set what as the _asyncState object and where to get it from?

  • ConnectionMultiplexerAsync() and DatabaseAsync() do some lazy initialization
  • The storage is intended to be added as singleton to the dependency injection
  • and then used in the services/controllers to store more complex data than simple strings.

using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Threading.Tasks;

namespace Test
{

    public class Settings
    {
        public string Config { get; set; }
    }

    public class MyAsyncRedisStorageService
    {

        private readonly Settings _settings;

        private IConnectionMultiplexer _connectionMultiplexer;
        private IDatabase _database;

        private object _asyncState;

        public MyAsyncRedisStorageService(IOptions<Settings> settings)
        {
            _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings));
            _asyncState = "what to use as asyncState object and when to get it from where?";
        }

        protected async Task<IConnectionMultiplexer> ConnectionMultiplexerAsync()
        {
            if (_connectionMultiplexer == null) _connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(_settings.Config);
            return _connectionMultiplexer;
        }

        protected async Task<IDatabase> DatabaseAsync()
        {

            if (_database == null)
            {
                IConnectionMultiplexer cm = await ConnectionMultiplexerAsync();
                _database = cm.GetDatabase();
            }
            return _database;

        }

        protected async Task<IDatabase> DatabaseAsync(object asyncStateObject)
        {

            if (_database == null)
            {
                IConnectionMultiplexer cm = await ConnectionMultiplexerAsync();
                _database = cm.GetDatabase(asyncState: asyncStateObject);
            }
            return _database;

        }

        public async Task<bool> StoreValueAsync(string key, string val)
        {
            //IDatabase db = await DatabaseAsync(_asyncState);
            IDatabase db = await DatabaseAsync();
            bool success = await db.StringSetAsync(key, val);
            return success;
        }

        public async Task<string> ReadValueAsync(string key)
        {
            //IDatabase db = await DatabaseAsync(_asyncState);
            IDatabase db = await DatabaseAsync();
            string value = await db.StringGetAsync(key);
            return value;
        }


    }

}

I am not sure if the statement means I have to set it if I want to use the asnychronous API or I can set it and get some benefit of doing so.

It means you can set it if you need to.

If the later what would that benefits be?

"Async state" is used by the Asynchronous Programming Model (APM) . You would need to provide async state only if your application heavily uses APM and you need to keep it that way for now. The Task-based Asynchronous Pattern (TAP) is capable of doing everything the APM can do, with simpler and more maintainable code. So you would only use APM if you have a large codebase and have not had the time to convert it yet. That's the only reason for passing "async state" to this API.

I don't know if/when to set what as the _asyncState object and where to get it from?

"Async state" is whatever your program wants it to be. The idea is that you provide an object to the Begin* method, and then you will get that same object in your callback when the asynchronous operation completes. This was much more useful many years ago before there were lambdas and variable capture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM