マルチスレッドアプリでクラス変数を使用するのは悪いことですか?
-
03-07-2019 - |
質問
マルチスレッド化が必要なプロジェクトを継承しました。ワーカースレッドで使用される3つの主要なクラスがあります。
基本クラス-クラスレベルのSqlDataAdapterとDataTableがあります。 継承されたクラス1-継承されたSqlDataAdapterとDataTableを使用します。 継承クラス2-継承されたSqlDataAdapterとDataTableを使用します。
すべてがうまくいくように見えますが、同時にテストするユーザーは2人だけです。
SqlDataAdapterとDataTableをクラスレベルの変数にするのは悪い考えですか?
更新 申し訳ありませんが、SqlTableAdapterではなくSqlDataAdapterです。言語はC#です。 SqlDataAdapterとDataTableは、System.Data.SqlClient名前空間からのものです。
基本クラスの一部を次に示します。
public abstract class BaseSync
{
#region Variables
internal SqlDataAdapter stageDataAdapter;
internal DataTable stageDataTable;
#endregion //Variables
}
パート2
すべての派生クラスが使用するシングルトンユーティリティクラスもあります。問題が発生するかどうかはわかりません。次のようになります。
public class Utility
{
private static readonly Utility _utility= new Utility();
private Utility()
{ }
public static Utility GetUtility()
{
return _utility;
}
public int GetAutoNumber(string tablename, string fieldname, string siteId)
{
string _tablename = tablename;
string _fieldname = fieldname;
...
}
internal MissingInfo NormalizeRow(DataRow dataRow)
{
MissingInfo retVal = MissingInfo.None;
//Num
if (dataRow["Num"] == DBNull.Value)
{
retVal =MissingInfo.Num;
dataRow["Num"] = 1;
}
...
}
}
解決
これは、オブジェクトのアクセスレベルに依存します。静的でない限り(VB.NETで共有)。各スレッドがオブジェクトの独自のインスタンスを持っている限り、オブジェクトにそれらを入れても大丈夫です。
興味深い状況になるのは、すべてのインスタンスで共有される静的メンバーです。
その長短は、コードを見る必要があるということです。
他のヒント
同期なしで異なるスレッドによって変数を変更することは、常に本当に悪い考えです。
ただし、これが当てはまるかどうかは言及しません。スレッドを作成する場合は、実行していることを計画して確認する必要があります。
変数に関する規則は、特にアプリケーションが進化する場合、変化する可能性のある場所が多いほど、競合状態になる可能性が高くなることです。
質問にはあまり情報がないため、具体的な回答を提供することは困難です。クラスレベルの変数(パブリックの場合)は、多くの場合、グローバル変数のように扱うことができるため、どこからでもアクセスできるため、破損のリスクが高まります。
可能なアプローチは、これらのフィールドを非表示にし、クラスレベルの関数を介してアクセスを提供することです。これらの変数への特定のアクセスポイントを作成したため、さらに多くのことができます。アプリケーションにそのオブジェクトへの直接かつ変更可能な参照を決して与えないように注意する必要があります。これにより、書き換えが必要になる場合がありますが、プログラムが安全になります。
マルチスレッドで非定数オブジェクトを共有する場合は、常に同期を行うことを検討する必要があります。そうしないと、いつか台無しになってしまいます...
そのため、クラス変数にしたい場合でも問題ありませんが、ロック機構を忘れずに作成してください。