如何在属于不同类的不同线程之间共享数据?
Posted
技术标签:
【中文标题】如何在属于不同类的不同线程之间共享数据?【英文标题】:How to share data between different threads which belong to different classes? 【发布时间】:2018-03-25 11:45:04 【问题描述】:我最近正在阅读有关 async/await 的内容,我想知道假设我们在某个 Web 应用程序中有 HttpContext
。此上下文包含有关userId
、sessionId
等的信息。我们的 Web 应用程序提供了一些数据,这些数据由在另一台计算机上执行的某些控制台应用程序使用。如果此控制台应用程序发生错误,我会将其写入日志文件。 userId
和 sessionId
也应写入此日志文件。但是在这个控制台应用程序中创建的每个线程都有自己的上下文。所以,我正在寻找一种将userId
和sessionId
设置为线程上下文的方法。我不想使用一些静态类或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();
【问题讨论】:
线程不属于类。您的代码无论如何都没有使用线程,它使用异步方法。不需要跨线程同步 - await 确保执行将在正确的上下文中继续。当然,除非你用searchService.ExecuteSearchAsync().Wait();
阻止它,这意味着没有 await
能够返回
不太确定你要做什么,但听起来你可以通过传递 userId 和 sessionId 作为方法参数来做到这一点
您的问题是什么?你想做什么?你遇到实际问题了吗?这段代码中唯一的问题是public void Execute()
和对Wait()
的调用。该方法应该是异步的
至于日志记录,您使用的是哪个记录器?不同的记录器使用不同的技术来传递环境属性,而不依赖于线程上下文,准确地说,因为这会随着任务而变化。如果您编写自己的记录器并遇到问题,请发布记录器的代码
@PanagiotisKanavos 我有一个 static
记录器类,它执行写入日志文件。它用于Web应用程序和控制台应用程序。它从线程上下文中获取数据。这是 Web 应用程序中的 HttpContext
。但我的吊顶申请中没有userId
和sessionId
。我认为我应该将其设置为控制台应用程序的上下文。
【参考方案1】:
几乎从来没有必要将数据“设置到线程上下文”,所以别想了。
考虑线程安全是件好事——大多数问题都是因为人们没有考虑。但是,在这种情况下不需要有两个原因:
从你所说的,userId 和 sessionId 在 这个例子的生活。许多请求可能同时运行,但 每个堆栈都有自己的用户 ID/会话 ID
我打赌 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();
【讨论】:
以上是关于如何在属于不同类的不同线程之间共享数据?的主要内容,如果未能解决你的问题,请参考以下文章