在 asmx Web 服务中为数据库 IO 生成线程的正确方法是什么?

发布于 2024-08-13 11:21:31 字数 1335 浏览 1 评论 0原文

我在一个方法中有一个简短的锁保护部分(完全服务于请求),它进行所有初始化(等等与日志相关)。所以一次只能有 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;
       }
    }

我的问题是:

  1. 如何生成一个非线程池线程最好的方式来处理 IO,以便线程池工作线程可以传播并且所有线程在锁保护部分花费最少的时间?

  2. 是_allData = newData;在 LoadAllSystemData 原子中?如果是,那么感觉是实现这一点的最佳方法,因此像 GetTables 这样的 GetXxx 方法不需要任何锁定!

  3. 有没有办法让 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:

  1. 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?

  2. 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!

  3. Is there any way to get LoadAllSystemData to be called before requests? For example on iisreset?

Thanks in advance for your answers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

全部不再 2024-08-20 11:21:31

Matti,您提出的多个问题都指向您的应用程序的最佳结构。我将您的问题总结为:

  • 在处理任何合法请求之前,如何预加载我的服务所需的数据?
  • 如何确保预加载的数据加载“一次”?
  • 如何按计划(即每 24 小时)刷新预加载的数据?

了解 Asp.Net 管道和事件结构将帮助您理解这些问题的答案。

首先,Asp.Net 管道在 Application_Start 中提供了一个一次性执行区域。每个应用程序周期都会触发一次。这也会在“iisreset”中触发,它会循环给定服务器的每个应用程序。但是,应用程序周期本身将根据其配置自行回收。所有这些都通过 IIS 设置进行控制。

其次,Asp.Net是一个请求系统;它不会为您触发刷新事件,您也不能将它本身用作调度程序。您需要一个外部代理来为您采取行动。

以下是您可以执行的操作:

  1. 将预加载的数据例程添加到Application_Start。
  2. 将网站的应用程序周期设置配置为每 24 小时一次。

这将确保您的数据通过 Application_Start 加载一次。它将确保您的数据在您的网站提供任何请求之前加载。最后,它将确保您的数据每 24 小时刷新一次。

以下是我做的事情:

  1. 将预加载的数据例程添加到Application_Start。
  2. 修改预加载数据例程以使用 Asp.Net 缓存,而不是静态使用。
  3. 修改查找数据以从缓存中检索数据,如果没有找到数据则重新加载。
  4. 为诊断/监控系统(即nagios)提供通过Web方法调用(即“preload_refresh()”)异步刷新数据的能力。

这将提供与上述解决方案基本相同的转发效果,但为您的服务提供更好的可靠性。

与往常一样,您的里程可能会有所不同。希望这有帮助。

Matti, you're asking multiple questions that point to the best structure for your application. I would summarize your questions as:

  • How do I pre-load data needed by my service prior to handling any legitimate requests?
  • How do I ensure the pre-loaded data is loaded "once"?
  • How do I refresh the pre-loaded data on a schedule, i.e. every 24 hours?

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:

  1. Add your pre-loaded data routine to Application_Start.
  2. Configure your web site's Application cycle settings for every 24 hours.

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:

  1. Add pre-loaded data routine to Application_Start.
  2. Modify pre-loaded data routine to use Asp.Net Cache, instead of static usage.
  3. Modify lookup data to retrieve data from cache, and re-load if data is not found.
  4. Provide capability for diagnostic/monitoring system, i.e. nagios, to refresh data asynchronously via web method call, i.e. "preload_refresh()".

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.

情何以堪。 2024-08-20 11:21:31

无论如何,为了回答您的部分问题,如果您想在应用程序上线后立即预填充数据,您可以使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文