在 asmx Web 服务中为数据库 IO 生成线程的正确方法是什么?
我在一个方法中有一个简短的锁保护部分(完全服务于请求),它进行所有初始化(等等与日志相关)。所以一次只能有 1 个线程。在本节中,如果未加载,我还会从数据库加载系统数据。这自然只在第一个请求上执行,并且花费时间并不重要,并且没有线程可以传播,因为它只执行一次(通过虚拟请求)。
static public void LoadAllSystemData() { SystemData newData = new SystemData(); //own type (etc. Hashtables in Hashtables). LoadTables(ref newData); LoadClasses(ref newData); LoadAllSysDescrs(ref newData); LoadFatFields(ref newData); LoadAllFields(ref newData); _allData = newData; }
在锁保护部分之后,并发线程仅通过读取来访问系统数据,不需要锁:
static public Hashtable GetTables() { return _allData.Tables; }
现在锁保护部分必须具有检查系统数据是否早于 24 小时并刷新它的方法。如果仅通过调用下面的方法(来自锁保护部分)来完成,则该线程需要很长时间并且没有其他线程可以进入锁保护部分。
static public void CheckStatus() { DateTime timeStamp = DateTime.Now; TimeSpan span = timeStamp.Subtract(_cacheTimeStamp); if (span.Hours >= 24) { LoadAllSystemData(); _cacheTimeStamp = DateTime.Now; } }
我的问题是:
如何生成一个非线程池线程最好的方式来处理 IO,以便线程池工作线程可以传播并且所有线程在锁保护部分花费最少的时间?
是_allData = newData;在 LoadAllSystemData 原子中?如果是,那么感觉是实现这一点的最佳方法,因此像 GetTables 这样的 GetXxx 方法不需要任何锁定!
有没有办法让 LoadAllSystemData 在请求之前被调用?例如在 iisreset 上?
预先感谢您的回答!
I have a short lock guarded section in a method (that serves the request entirely) that makes all initializations (etc. log-related). So only 1 thread can be there at time. In this section I also load system data from database if not loaded. This is naturally executed only on 1st request and it does not matter it takes time and no threads can propagate since it's done only once (by dummy request).
static public void LoadAllSystemData() { SystemData newData = new SystemData(); //own type (etc. Hashtables in Hashtables). LoadTables(ref newData); LoadClasses(ref newData); LoadAllSysDescrs(ref newData); LoadFatFields(ref newData); LoadAllFields(ref newData); _allData = newData; }
After the lock-guarded section the system data is accessed from concurrent threads only by reading and no locks are needed:
static public Hashtable GetTables() { return _allData.Tables; }
Now the lock guarded section must have method that checks if system data is older than 24h and refresh it. If it done just by calling method (from lock guarded section) below that thread takes a long time and no other thread can enter the lock guarded section.
static public void CheckStatus() { DateTime timeStamp = DateTime.Now; TimeSpan span = timeStamp.Subtract(_cacheTimeStamp); if (span.Hours >= 24) { LoadAllSystemData(); _cacheTimeStamp = DateTime.Now; } }
My questions are:
How to spawn a non-threadpool thread best way to handle IO so the threadpool worker thread can propagate and all the threads spend minimum time in lock guarded section?
Is the _allData = newData; in LoadAllSystemData atomic? If it is, it feels the best way to implement that so GetXxx-methods like GetTables do not need any locking!
Is there any way to get LoadAllSystemData to be called before requests? For example on iisreset?
Thanks in advance for your answers!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Matti,您提出的多个问题都指向您的应用程序的最佳结构。我将您的问题总结为:
了解 Asp.Net 管道和事件结构将帮助您理解这些问题的答案。
首先,Asp.Net 管道在 Application_Start 中提供了一个一次性执行区域。每个应用程序周期都会触发一次。这也会在“iisreset”中触发,它会循环给定服务器的每个应用程序。但是,应用程序周期本身将根据其配置自行回收。所有这些都通过 IIS 设置进行控制。
其次,Asp.Net是一个请求系统;它不会为您触发刷新事件,您也不能将它本身用作调度程序。您需要一个外部代理来为您采取行动。
以下是您可以执行的操作:
这将确保您的数据通过 Application_Start 加载一次。它将确保您的数据在您的网站提供任何请求之前加载。最后,它将确保您的数据每 24 小时刷新一次。
以下是我会做的事情:
这将提供与上述解决方案基本相同的转发效果,但为您的服务提供更好的可靠性。
与往常一样,您的里程可能会有所不同。希望这有帮助。
Matti, you're asking multiple questions that point to the best structure for your application. I would summarize your questions as:
Understanding the Asp.Net pipeline and event structure will help you understand the answers to these questions.
First, the Asp.Net pipeline provides a one-time execution region in Application_Start. This is fired once per application cycle. This would also fire in 'iisreset', which cycles every application for a given server. However, application cycles themselves will recycle on their own, based on their configuration. All of which are controlled through IIS settings.
Second, Asp.Net is a request system; it won't fire refresh events for you, nor can you use it by itself as a scheduler. You need an outside agent to act on that for you.
Here's what you could do:
This would ensure your data is loaded once, via Application_Start. It would ensure your data is loaded prior to your site serving any requests. Last, it would ensure your data is refreshed every 24 hours.
Here's what I would do:
This would provide essentially the same forward effect as the above solution, but with better reliability for your service.
As always, your mileage may vary. Hope this helps.
无论如何,为了回答您的部分问题,如果您想在应用程序上线后立即预填充数据,您可以使用 Global.asax 中的“Application_Start”方法在应用程序启动时执行该语句。
To answer part of your question anyway, you can use the "Application_Start" method in the Global.asax to execute the statement on the start of the application if you want to pre-fill the data as soon as the application comes online.