0

我最近在阅读有关 async/await 的内容,我想知道如何在属于不同类的不同线程之间共享数据?假设我们HttpContext在某个 Web 应用程序中有 。此上下文包含有关userIdsessionId的信息。我们的 Web 应用程序提供了一些数据,这些数据由在另一台计算机上执行的某些控制台应用程序使用。如果此控制台应用程序发生错误,我会将其写入日志文件。userId并且sessionId也应该写入这个日志文件。但是在这个控制台应用程序中创建的每个线程都有自己的上下文。所以,我正在寻找一种设置userIdsessionId线程上下文的方法。我不想使用一些静态类或volatile字段。我在下面放置了一个简单的控制台应用程序示例。

    public sealed class MainService
    {
        /// <summary>
        /// The main method which is called.
        /// </summary>
        public void Execute()
        {
            try
            {
                searchService.ExecuteSearchAsync().Wait();
            }
            catch (Exception e)
            {
                // gets additional info (userId, sessionId) from the thread context
                StaticLoggerClass.LogError(e);
            }
        }
    }

    public sealed class SearchService
    {
        private IRepository  repository = new Repository();

        public async Task ExecuteSearchAsync()
        {
            try
            {
                var result = await this.GetResultsAsync();
            }
            catch (Exception e)
            {
                // gets additional info (userId, sessionId) from the thread context
                StaticLoggerClass.LogError(e);
            }
        }

        private async Task<ResultModel> GetResultsAsync()
        {
            var result = this.repository.GetAsync();
        }
    }

    public sealed class Repository
    {
        private IClient client;

        public async Task<Entity> GetAsync()
        {
            return await client.GetResultAsync();
        }
    }
4

1 回答 1

1

几乎从来没有必要将数据“设置到线程上下文”,所以把它放在你的脑海中。

考虑线程安全是件好事——大多数问题都是因为人们没有考虑。但是,在这种情况下,不需要两个原因:

  1. 从你所说的,userId 和 sessionId 在这个例子的生命周期中不会改变。许多请求可能同时运行,但每个堆栈都有自己的用户 ID/会话 ID

  2. 我打赌 userid/sessionid 是不可变类型 - 即不能更改。如果它们是字符串、整数或任何值类型,就会出现这种情况。

因此,考虑到这一点,您可以这样做:

public sealed class MainService
{
    /// <summary>
    /// The main method which is called.
    /// </summary>
    public void Execute()
    {
        try
        {
            // somehow get the userid/sessionid, you don't say where these are from
            var userId = "?";
            var sessionId = "?"

            searchService.ExecuteSearchAsync(userId, sessionId).Wait();
        }
        catch (Exception e)
        {
            // gets additional info (userId, sessionId) from the thread context
            StaticLoggerClass.LogError(e);
        }
    }
}

public sealed class SearchService
{
    private IRepository  repository = new Repository();

    public async Task ExecuteSearchAsync(string userId, string sessionId)
    {
        try
        {
            var result = await this.GetResultsAsync();
        }
        catch (Exception e)
        {
            // gets additional info (userId, sessionId) from the thread context
            StaticLoggerClass.LogError($"userId={userId}; sessionId={sessionId}; error={e}");
        }
    }

    // ........ 
    private async Task<ResultModel> GetResultsAsync()
    {
        var result = this.repository.GetAsync();
    }
}
于 2017-10-13T11:53:49.850 回答