我需要一些關於我寫的應用程序的建議。我遇到的問題是由於我的DAL和連接到我的SQL Server 2008數據庫沒有關閉,但是我查看了我的代碼,並且每個連接總是被關閉。C#多線程應用程序和SQL連接幫助
該應用程序是一個多線程應用程序,用於檢索一組記錄,並在處理記錄時更新有關記錄的信息。
這裏是流量:
的管理員可以設置運行的線程數量拉動能力和多少條記錄每個線程。
這裏是運行他們點擊開始後的代碼:
適配器是抽象的在這裏我DAL是他們看起來像一個示例:
public class UserDetailsAdapter: IDataAdapter<UserDetails>
{
private IUserDetailFactory _factory;
public UserDetailsAdapter()
{
_factory = new CampaignFactory();
}
public UserDetails FindById(int id){
return _factory.FindById(id);
}
}
只要_factory把它叫做處理SQL並立即關閉連接。
代碼爲線程應用程序:
private int _recordsPerthread;
private int _threadCount;
public void RunDetails()
{
//create an adapter instance that is an abstration
//of the data factory layer
var adapter = new UserDetailsAdapter();
for (var i = 1; i <= _threadCount; i++)
{
//This adater makes a call tot he databse to pull X amount of records and
//set a lock filed so the next set of records that are pulled are differnt.
var details = adapter.FindTopDetailsInQueue(_recordsPerthread);
if (details != null)
{
var parameters = new ArrayList {i, details};
ThreadPool.QueueUserWorkItem(ThreadWorker, parameters);
}
else
{
break;
}
}
}
private void ThreadWorker(object parametersList)
{
var parms = (ArrayList) parametersList;
var threadCount = (int) parms[0];
var details = (List<UserDetails>) parms[1];
var adapter = new DetailsAdapter();
//we keep running until there are no records left inthe Database
while (!_noRecordsInPool)
{
foreach (var detail in details)
{
var userAdapter = new UserAdapter();
var domainAdapter = new DomainAdapter();
var user = userAdapter.FindById(detail.UserId);
var domain = domainAdapter.FindById(detail.DomainId);
//...do some work here......
adapter.Update(detail);
}
if (!_noRecordsInPool)
{
details = adapter.FindTopDetailsInQueue(_recordsPerthread);
if (details == null || details.Count <= 0)
{
_noRecordsInPool = true;
break;
}
}
}
}
應用崩潰,因爲似乎有連接問題的數據庫。看我的日誌文件的DAL我看到這個:
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached
當我在一個線程運行它工作正常。我猜測,當我在多個線程中使用他時,我顯然與DB建立了太多的連接。關於如何在多個線程中保持這種運行的任何想法,並確保數據庫不會給我任何錯誤。
更新: 我想我的問題可能是我的數據庫中的死鎖。這裏是運行在SQL代碼WHE我得到一個死鎖錯誤:
WITH cte AS (
SELECT TOP (@topCount) *
FROM
dbo.UserDetails WITH (READPAST)
WHERE
dbo.UserDetails where IsLocked = 0)
UPDATE cte
SET
IsLocked = 1
OUTPUT INSERTED.*;
我以前從來沒有過與此代碼的問題(在其他應用程序)。我重新整理了我的索引,因爲它們99%是分散的。這沒有幫助。我在這裏不知所措。
這是一個好主意...... – DDiVita 2010-10-24 13:52:09
調用'.Close()'實際上並不會在使用池時關閉連接。調用'.Dispose()'也不會關閉連接。通過調用'.Close()'或'.Dispose()',將連接釋放到池中。(如果在處理之前未調用,則.Dispose()將調用'.Close()')。總是調用'.Dispose()'(最好使用using語句),並且如果花哨的話可以選擇調用'.Close()'。 – Mark 2010-10-25 21:44:10
這就是我所說的「不需要明確地關閉它們」(我不知道'.Close()* * still *不會明確地關閉它們)。 'using'塊在處理完作用域後會處理'.Dispose()',並且DataAdapter需要隱式打開。 – 2010-10-26 05:01:39