对 SQL 的调用会导致我的多线程应用程序出现瓶颈吗?

发布于 2024-10-24 00:31:48 字数 1174 浏览 6 评论 0原文

在我的多线程应用程序中调用 SQL 是否会导致应用程序成为瓶颈?

我使用的逻辑有效并且符合最佳实践吗?

static void Main(string[] args)
    {
        try
        {
        TcpListener listener = new TcpListener(IPAddress.Any, 8000);
        TcpClient client;
        listener.Start();

        while (true) // Add your exit flag here
        {
            client = listener.AcceptTcpClient();
            ThreadPool.QueueUserWorkItem(ThreadProc, client);
        }
        }
        catch (Exception ex)
        {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
        }

    }//Main


    private static void ThreadProc(object obj)
    {
        var client = (TcpClient)obj;
        // Do your work here...

        NetworkStream ns = client.GetStream();

        using (StreamWriter writer = new StreamWriter(ns))
        {
           writer.WriteLine("220 SMTP server ready.");
           writer.Flush();

           using (StreamReader reader = new StreamReader(ns))
           {
              //parse + persist smtp message here...
              //save email message parts to a Email table in SQL SVR(from, to, body...)
           }
        }
    }//ThreadProc

will the call to SQL in my multi threaded application cause the app to be bottleneck?

Is the logic i am using valid and conform to best practice?

static void Main(string[] args)
    {
        try
        {
        TcpListener listener = new TcpListener(IPAddress.Any, 8000);
        TcpClient client;
        listener.Start();

        while (true) // Add your exit flag here
        {
            client = listener.AcceptTcpClient();
            ThreadPool.QueueUserWorkItem(ThreadProc, client);
        }
        }
        catch (Exception ex)
        {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
        }

    }//Main


    private static void ThreadProc(object obj)
    {
        var client = (TcpClient)obj;
        // Do your work here...

        NetworkStream ns = client.GetStream();

        using (StreamWriter writer = new StreamWriter(ns))
        {
           writer.WriteLine("220 SMTP server ready.");
           writer.Flush();

           using (StreamReader reader = new StreamReader(ns))
           {
              //parse + persist smtp message here...
              //save email message parts to a Email table in SQL SVR(from, to, body...)
           }
        }
    }//ThreadProc

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

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

发布评论

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

评论(1

吻风 2024-10-31 00:31:48

我解决这个问题的方法是拥有一个队列,您可以在其中添加要解析和持久化的内容,然后由一组线程(甚至只是一个线程)提供服务,这取决于预期的吞吐量。这里的关键是尽快为队列提供服务,但如果有积压,也不会影响添加更多项目。

编辑:

你的场景中有很多未知因素,所以我的解决方案同样模糊,但我应该解释一下。

你的问题是我不知道你的sql将运行多长时间,或者如果失败/超时应该采取什么操作,或者你期望排队或运行多少个sql语句。

我的解决方案是首先提取面向公众的接口,用于 a) 对操作进行排队和 b) 处理操作。这使您有机会在以后甚至现在将排队机制切换为更合适的机制。

因此,假设您正在对工作项进行排队,并且数据库停止响应。突然之间,什么都没有被保存。这会影响您的应用程序的功能吗?这里是否存在任何交易问题?将工作项写入 MSMQ 之类的东西也许会更好吗? SQL Server 还有一个代理服务,它可以很好地满足您的需求。

所以我不打算添加任何代码,而是从这些角度思考:

1)指定接口 接口:

public interface QueueWorkItem
{
无效AddWorkItemToQueue(工作项项目);
ConsumeWorkItem

公共接口
{
布尔 ItemsInQueue {获取;}
工作项 GetNextItem();

您不必使用这些,这只是示例

2)构建一个实现接口的类
这是有趣的一点,您必须担心线程和阻塞(寻找生产者消费者模式)您始终可以使用线程池并让 ConsumeWorkItem 实际上什么都不做。

最后,我们来谈谈线程池。很好,但是您对它没有太多控制权,并且不能保证其中运行的所有线程都是您的。

希望有帮助。

The way I would approach this is to have a Queue which you add the stuff you're going to parse and persist and then have that serviced by a pool of threads, or even just one thread, it depends on the expected throughput. The key here is the queue is serviced as soon as possible, but if there is a backlog it doesn't affect adding more items.

Edit:

There are a bunch of unknowns in your scenario, so my solution was equally vague, but I should of explained that.

The problem with your problem is I don't know how long your sql will run, or what action should be taken if it fails/times out, or how many of these sql statements you're expecting to queue up or run.

My solution would be to first extract the public facing interface for a) queuing an operation and b) processing an operation. this gives you the opportunity to, at a later date, or even now, switch out the queuing mechanism for something more appropriate.

So, take the case where by you are queuing work items, and the database stops responding. Suddenly nothing is being saved. Does that affect what your application does? Is there any sort of transactional issue here? Would it be better perhaps to be writing the work item to something like MSMQ? SQL Server also has a broker service which could be pretty spot on for what you want.

So I'm not going to add any code, but think in these terms:

1) Specify interfaces interface:

public interface QueueWorkItem
{
void AddWorkItemToQueue(WorkItem item);
}

public interface ConsumeWorkItem
{
bool ItemsInQueue {get;}
WorkItem GetNextItem();
}

You don't have to use these, it's just examples.

2) Build a class that implements the interfaces
This is the fun bit, you have to worry about threading and blocking (Look for producer consumer pattern) You could always use the threadpool and have the ConsumeWorkItem do nothing really.

Finally, lets talk about the threadpool. It's fine, but you don't have much control over it, and there's no guarantee that all the threads running in it are yours.

Hope that helps.

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