2012-03-02 8 views
0

私は書き直している古いC#アプリケーションでMySQL .Netライブラリを使用しています。データアクセスレイヤーはむしろ時代遅れですが、私はそれを最大限に活用しようとしています。しかし、今は本当に面倒なスレッド問題に遭遇しました。私のスタティックDALのMySQLスレッディング問題

レポートを処理するために使用される一連の約20のSelect文があります。完了までに約5秒かかりますし、Select文が実行されている間にプログレスバーを表示しています。私は、単純なThreadPoolの呼び出しを経由して操作を開始しています:

[LATER EDIT:何が起こることは私が原因私のUIのバグに二回以下のメソッドを呼び出したということである - これは質問を切り下げるませんが、単に私のスレッドが互いに競争した理由を説明する。]

ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateChart)); 
  • 時にはそれが動作します。
  • 「可能なIOストリーム競合状態」でクラッシュすることがあります。
  • 「接続が有効かつ有効である」とクラッシュすることがあります。
  • "オブジェクト参照が設定されていません..."とクラッシュすることがあります。

私のDALのすべてのクラスは、これがパフォーマンスを向上させる良い方法だと思っていたので静的です(小さな操作ごとに新しいクラスインスタンスを作成する必要はありません)。

そして、すべての私のDALクラスは、接続を構築し、同じ「ルート」DALクラスを使用します。

public static class MySQLConnectionBuilder 
{ 

private static MySqlConnectionStringBuilder ConnectionStringBuilder = new MySqlConnectionStringBuilder(); 

//I'm initializing the ConnectionStringBuilder with my server password & address. 

public static MySqlConnection GetConnection() 
{ 
    return new MySqlConnection(ConnectionStringBuilder.ConnectionString); 
} 

} 

すべての私のDALのクラスは、クラッシュの機能と同様な機能を持っています。クラッシュ関数は次のようになります。

public static STDS.UserPresence.user_presenceDataTable GetPresence (int aUserID, DateTime aStart, DateTime aEnd) 
{ 
    ta.Connection = MySQLConnectionBuilder.GetConnection(); 
    ds = ta.GetPresenceForUserBetweenDates(aUserID, aStart, aEnd); 
    ta.Connection.Close(); 
    return ds; 
} 

アイデア?改善のヒント?よりオブジェクト指向の(インスタンス駆動型)DALに切り替えると、スレッドの問題はなくなりますか?必ずしも同じスレッドで作成した接続 -

+0

5秒遅れで間違っているか、それともSQLコールごとに5秒かかるのですか?20 x 5?投稿されたものから、私はあなたのDb接続と呼び出しをどのようにしてConnectionPoolingとパフォーマンスに関するいくつかの調査をしています。 – Lloyd

+0

MySQLライブラリはConnectionPoolingを使用していますが、私のマルチスレッドの状況では正しく動作しません。だからこそ私はここに投稿しました。なぜなら、私は可能な解決策が不思議だからです。 5秒間:超高速でなければならないデスクトップアプリケーションのボタンをクリックすると、長い時間がかかります。それだけでなく、今後数か月のうちにこの期間が20秒になると予想しています。 – Axonn

+0

Using(MySqlConnection conn = new MySqlConnection(connectionString)){{}}を使用し、フレームワークが設計どおりにプールを管理できるように、それぞれの静的メソッドで新しいMySqlConnectionを定義、初期化、あなたがしていることは、単に自分の混乱を作り出します。現在のメソッドで例外がスローされた場合、接続はどのように閉じられていますか? – Lloyd

答えて

1

ライン

ta.Connection.Close() 

は最後ta.Connectionに割り当てられた接続を閉じます。これにより、クエリが現在別のスレッドで実行されている接続が切断されることがあります。

[ThreadStatic] 
private static MySqlConnection connection; 

私はあなたの最後のためにこのアプローチを使用することはありません。

あなたは、これは何が起こっているかであるかどうかを迅速に判定する場合

は、クラス内の[ThreadStatic]属性での taポイントを接続変数をマーク解決策は、GCによって収集されない可能性があるためです。

簡単な解決策は、(あなたのクラスは、他のマルチスレッドの問題がある場合その問題のために、私が判断することはできません)あなたはグローバルConnectionクラスを削除することができ、あなたのDALの方法のそれぞれにパラメータとして接続を追加することです:

public static STDS.UserPresence.user_presenceDataTable GetPresence (int aUserID, DateTime aStart, DateTime aEnd) 
{ 
    using (MySqlConnection connection = MySQLConnectionBuilder.GetConnection()) 
    { 
     ds = ta.GetPresenceForUserBetweenDates(connection, aUserID, aStart, aEnd); 
     return ds; 
    } 
} 

スレッディングの問題は、決して消えません。注意が必要です。何が起こっているのかわからない場合は、わずかなパフォーマンスの向上を忘れてしまいます(クエリが5秒かかると、静的クラスを使用するとパフォーマンスが1%低下します)。

+0

私はここの他の場所でも、そのThreadStatic属性について読んでいます。私はそれが問題を治療するかどうかを調べるつもりです。しかし、全体的には、私は静的なクラスをダンプし、インスタンスのために行くことをお勧めしたいと思います。もう1つのことは、 "接続をパラメータとして追加する"と言ったが、変更したコードは代わりに "using"ステートメントを使用する。それはあなたが意味することですか? – Axonn

+0

私は試しましたが、動作しません。私はThreadStaticでグローバル変数を宣言し、このような関数で初期化しました: "MCon = WTCoreMySQLDB.GetConnection(); MConはグローバル変数です。次に、メソッドと呼ばれるテーブルアダプタにMConを割り当て、MConを閉じました。時には、私はまだ誤りがあります。それは一定ではありません(どんなスレッド状況でも同じです)。 – Axonn

+0

'使用する '部分は、接続へのローカル参照のみが保持され、他のスレッドはそれにアクセスできません。次に、接続は 'GetPresenceForUserBetweenDates'メソッドに渡されます。そのため、メソッドはグローバル接続インスタンスにアクセスする必要はありません。全体的には、インスタンスを作成することについて心配する必要はありません。最初に動作する読み取り可能なコードを作成し、問題が発生するとパフォーマンスのボトルネックを見つけます(そのボトルネックは20x5秒のクエリになります)。 –