トップ回答者
BackgroundWorkerの競合

質問
-
BackgroundWorkerを使ってソケット通信を行う処理を作っているのですが、
複数のワーカーを起動するとどうも処理が競合が起きているようで、
「オブジェクト参照がオブジェクトインスタンスに格納されていません」
というエラーが起きます。
sleepを100ミリ秒でも入れると発生しなくなります。
エラーが発生するのは通信ログをデータベースにINSERTする部分で、
共通のFunctionとして作成しているのですが、
複数のスレッドから同じファンクションが呼ばれると関数の内部の変数で競合がおきるのでしょうか?
別のスレッドから呼ばれるのであればそれぞれでリソースを確保するのかと思ったのですが。
マルチスレッドのプログラムを作ったことがないのでいまひとつよく分かりません。
よろしくお願いいたします。
回答
-
trapemiya様
回答ありがとうございます。
その後、いろいろいじっているうちに解消しました。
スレッドを一つだけ動かした場合にも発生したので、
どうもBackgroundWorkerの競合というわけではないようです。
DB接続の部分はOracleとPostgreSQLの両方のケースに簡単に切り替えられるよう、
OracleConnectoin,NpgsqlConnectionオブジェクトを共通の親クラスであるDBConnectionオブジェクトに
代入して処理するような形にしていたのですが、それをやめたら解消しました。
はっきりした原因はよくわからないままですが、とりあえず解消したのでこれで行こうと思います。
ありがとうございました。
- 回答としてマーク 山本春海 2011年4月28日 9:05
すべての返信
-
複数のスレッドから同じファンクションが呼ばれると関数の内部の変数で競合がおきるのでしょうか?
起きます。複数のスレッドからアクセスされるのであれば、スレッドセーフと言ってマルチスレッドでも安全に動作するように作らなければなりません。以下などを読まれると良いと思います。.NETマルチスレッド・プログラミング入門
http://www.atmarkit.co.jp/fdotnet/mthread/index/index.html
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/ -
trapemiya様
回答ありがとうございます。
教えていただいた記事ですが、読んだことがありました。
BackgroundWorkerの存在を知らなかったときにvb.netでマルチスレッドを作る方法を勉強しているときにひととおり見ました。
ここで挙げられている例はメインスレッドで作成したbankクラスをスレッドセーフでないスレッドに渡して処理しているために
競合が起きているのだと思いますが、
今回の私が作成した処理は競合が起きないように、基本的にスレッドから呼び出しもとの変数などにはアクセスしないように作ったつもりです。
起動引数用の変数も呼び出すスレッドごとに変えました。
ただ、DBアクセスの処理は共通化して別のクラスにしているので、そこで競合が起きているということでしょうか。
それぞれのスレッドの中で新たにクラスをnewするので、競合は起きないと思ったのですが。
よろしくお願いします。
-
基本的なことはご理解されて作られているとのことですね。失礼いたしました。
ただ、DBアクセスの処理は共通化して別のクラスにしているので、そこで競合が起きているということでしょうか。
さすがに情報が乏しくて何とも言えないのですが、問題を切り分けていくしかないと思います。DBアクセスが怪しいとのことですから、例えば実際にinsert文を発行しないとか、DBアクセスのクラス自体を実行しないようにコメントアウトしてみるなどして、絞り込まれてはいかがでしょうか?
また、「オブジェクト参照がオブジェクトインスタンスに格納されていません」という例外が発生しているようですが、そのオブジェクトはやはりDBアクセス周りのオブジェクトなのでしょうか?
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/ -
trapemiya様
回答ありがとうございます。
その後、いろいろいじっているうちに解消しました。
スレッドを一つだけ動かした場合にも発生したので、
どうもBackgroundWorkerの競合というわけではないようです。
DB接続の部分はOracleとPostgreSQLの両方のケースに簡単に切り替えられるよう、
OracleConnectoin,NpgsqlConnectionオブジェクトを共通の親クラスであるDBConnectionオブジェクトに
代入して処理するような形にしていたのですが、それをやめたら解消しました。
はっきりした原因はよくわからないままですが、とりあえず解消したのでこれで行こうと思います。
ありがとうございました。
- 回答としてマーク 山本春海 2011年4月28日 9:05