c#am我正确处理多个线程

时间:2009-01-30 16:13:17

标签: c# multithreading

我有一个winform应用程序,它创建了5个线程来连接并在非常慢的连接上从数据库中检索信息(某些查询需要90秒)。每个线程都有自己的类实例来执行sql查询。当检索到查询的数据时,主线程将由运行查询的类触发的事件通知。在接收到事件之后,主线程的各种组件被更新,例如显示项目或仅仅是数据表保存数据以供以后使用。根据查询的信息类型,以不同的间隔重复查询。

一切都很好......但我并不开心。我觉得它应该以不同的方式完成,但我不确定哪种方式。

以下是我目前如何设置每个帖子:

string ConnectionString = @"Data Source=mySrv;Initial Catalog=myTbl;Connect Timeout=30;UID=sa;pwd=mypwd";


//thread #1    
 SQL_Requests ReasonRequests;
 Thread Reason_Thread;
 ReasonRequests = new SQL_Requests();
 ReasonRequests.ProcessFinished += new SQL_Requests.ProcessFinished(ReasonRequests_Completed);
 Reason_Thread = new Thread(ReasonRequests.ExecuteQuery);
 ReasonRequests.DBQueryString = "select * from ReasonTable where staralingment = goodalignment"
 ReasonRequests.DBConnection = ConnectionString;

//thread #2
SQL_Requests EventRequests; 
Thread Event_Thread;
EventRequests = new SQL_Requests();
EventRequests.ProcessFinished += new SQL_Requests.ProcessFinished(EventRequests_Completed);
Event_Thread= new Thread(EventRequests.ExecuteQuery);

EventRequests.DBQueryString = "select * from EventTable where somefield = somevalue"
EventRequests.DBConnection = ConnectionString;

每个Thread.start都有不同的间隔。

任何建议?

5 个答案:

答案 0 :(得分:5)

您应该看一下执行查询的异步方法,即http://msdn.microsoft.com/en-ca/library/system.data.sqlclient.sqlcommand.beginexecutereader.aspx

,而不是启动自己的线程。

您提到您的连接速度很慢,是低带宽连接还是高延迟连接?如果由于带宽不足而导致数据缓慢返回多个查询会使事情变慢。如果只是一个延迟问题,一次执行多个查询可能会提高响应能力。

如果您正在执行一组相关查询,您可能还需要考虑将它们分组到一个命令中,或者使用存储过程将它们分组到服务器上。您可以使用SqlDataReader上的NextResult方法获取其他结果集。

答案 1 :(得分:4)

如果您的线程通过非常慢的连接从同一服务器获取数据(意味着有限的带宽是主要因素),您将无法通过使用多个线程获得任何东西。

OTOH使用单个线程进行所有数据获取操作实际上会更好:

  • 您将在一段时间后获得部分数据,因此您可以使用它更新UI。并行获取可能会分割带宽,并且您将获得很长时间没有任何数据,并且最终结果将很快到达。您的用户界面看起来不那么敏感。

  • 如果选择在服务器上导致大量I / O,那么不让它们并行执行实际上可以带来更好的吞吐量。考虑其他操作也将在服务器上执行。

恕我直言,您应该将提取保留在线程中以获得最佳的UI响应,但只使用一个。

编辑:您在评论中说明提取可能需要不同的时间。如果您可以估计哪些查询最快完成传输,请先执行它们。当然还假设数据传输占用大部分时间,而不是服务器上的查询执行。

如果你无法估计查询需要多长时间,或者带宽不是唯一的限制,那么使用多个线程当然可能最适合你。

答案 2 :(得分:2)

您想要执行此操作的典型原因是,如果5个数据库查询中的每个查询都很长,并且通过并行运行它们可以获得一些性能提升。如果您不希望通过这样做获得性能提升,我只需使用一个线程来完成数据库工作并将其进度报告给UI。

如果从并行处理中获得性能优势,我将使用内置线程池(System.Threading.ThreadPool.QueueUserWorkItem)。除非您需要对线程进行更多控制,否则线程池非常适合“即发即忘”类型的操作。您排队操作,并在完成后调用委托。

答案 3 :(得分:1)

在不知情的情况下,这也会让我的口味变得不好。我确信它有效。是否危险取决于您的主类是否是线程安全的。听起来你需要做一些严肃的测试:当两个请求同时完成时会发生什么,两个请求只是用相同的数据做了什么。

老实说,如果我要寻找一种“不同的方式”来做这件事,我可能会跳过对数据库的多线程访问,让一个线程完成所有的数据库工作,工作线程做任何额外的工作需要发生的工作(如果有的话),然后报告回主线程以进行数据库访问。

答案 4 :(得分:0)

请考虑任务并行性,而不是使用纯线程来开发并​​发软件。

请阅读以下文章: http://blog.rednael.com/2009/02/05/ParallelProgrammingUsingTheParallelFramework.aspx http://blog.rednael.com/2009/03/16/ParallelFrameworkDownloadAndSupport.aspx

这些是关于基本并行编程的文章,还包含有关并行性背景的其他文章的参考。包括C#.Net中的示例。此外,它描述了一个轻量级并行框架来处理任务。与其他一些框架相反,这个框架非常轻巧且易于使用。 阅读这些文章后,您应该能够使用并行性编写代码。

此致 马亭