c#线程特定的存储(喜欢)访问
因此,我目前有一个应用程序(简化),该应用程序获取ID并提出Web请求,并且我正在尝试为此实现一个记录器。当前的方法是创建一个简单的静态LoggingHelper类,我可以从程序中的任何地方调用LoggingHelper.log(URL),以将URL记录到列表中,并在我的最终报告中为所提供的ID记录,其中包括最后的列表。我的报告对象在其构造函数中调用logginghelper.initialize()以创建一个新的空列表。
public static class LoggingHelper
{
static List<string> _urlLog;
public static void Initialize()
{
_urlLog = new List<string>();
}
public static void Log(String s)
{
_urlLog.Add(s);
}
public static List<String> GetLogs()
{
return _urlLog;
}
}
测试时,这在我本地机器上非常有效,因为我只能每次运行单个ID。但是,当部署此功能时,该过程最多可以在同一应用程序中并行运行8个ID,这意味着我的静态列表现在与完全同时发生的所有8个运行共享,因为静态变量始终由过程中的所有线程共享。部署后,这会导致从错误的运行写入错误报告中的日志,因为该过程中的不同线程都同时运行并写入相同的静态实例。
通常,我只是将列表初始化为报告的成员变量并直接登录,但是在我需要调用日志函数的地方,我无法访问报告对象,这就是为什么我使用静态变量和访问者。
我想知道是否有相当于 thread_local>如果那对我的案件有效,或者是否有人对实施此情况有任何其他建议。我想避免对我的报告对象的引用(可以保存列表的成员变量)。
我想到了使用单身人士,但由于实例变量是静态的,但我仍然会遇到相同的问题,它仍然可以将相同的共享引用对列表保存。
关于我如何实现每次运行唯一的列表的任何想法,同时仍允许静态关键字提供的全局访问?
请让我知道是否需要任何澄清或其他详细信息,处理多个在这种特定情况下,线程对我来说是新的。谢谢!
So I currently have an application (simplified) that takes an ID and makes Web Requests and I am trying to implement a logger for this. The current approach was to create a simple static LoggingHelper class which I can call LoggingHelper.Log(url) from anywhere in my program to log the URL to a list and in my final report for the supplied ID, include the list at the end. My Report object calls LoggingHelper.Initialize() in its constructor to create a new empty list.
public static class LoggingHelper
{
static List<string> _urlLog;
public static void Initialize()
{
_urlLog = new List<string>();
}
public static void Log(String s)
{
_urlLog.Add(s);
}
public static List<String> GetLogs()
{
return _urlLog;
}
}
This works perfectly on my local machine when testing since I am only able to run a single ID per run. However when this is deployed, the process can run up to 8 IDs in parallel all using the same application, which means my static list is now shared by all 8 runs that are happening at the exact same time since static variables are always shared by all the threads in the process. Once deployed, this causes logs from the wrong run being written to the wrong report since different threads within the process are all running at the same time and writing to the same static instance.
Normally I would just initialize the list as an member variable for my report and log it directly, but in the places that I need to call the Log function, I have no access to the Report object which is why I used a static variable and accessor.
I was wondering if there was an equivalent of thread_local from C++ in C# (and if that would even work for my case) or if anyone had any other suggestions on going about implementing this. Passing a reference to my report object (which would could hold an member variable of List) is something I would like to avoid.
I thought of using a Singleton but I will still have the same issue since the instance variable is static it would still hold the same shared reference to the list.
Any ideas on how I would implement a list that is unique to each run while still allowing the global access that the static keyword provides?
Please let me know if any clarification or additional details are needed, dealing with multiple threads in this specific case is rather new to me. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如上所述,
threadlocal&lt; t&gt;
类旨在处理此类要求。也就是说,听起来您需要在异步边界上持续存在,这需要asynclocal&lt; t&gt;
类。请注意,这消除了您
initialize()
方法的需求。您可以使用以下内容进行测试:
输出以下内容:
请注意,在此示例中,不同的线程在多个async边界上编写各种日志调用,但是每个async-bound list仅包含两个项目,正如预期的。
As mentioned in the above comment, the
ThreadLocal<T>
class is designed to handle this type of requirement. That said, it sounds like you need to persist across async boundaries, which requires theAsyncLocal<T>
class instead.Note that this eliminates the need for your
Initialize()
method.You can test this with the following:
which outputs the following:
Note that in this example, different threads are writing the various log calls across multiple async boundaries, but each async-bound list only contains two items, as expected.