2

C#の私のアプリはこのように動作しています。構成ファイル(スレッドの動的作成)の値と同じ数のスレッドを開始します。すべてのスレッドが実行しているのは、DBに移動し、ストアドプロシージャを呼び出すことです(60のスレッドがある場合、デッドロックが発生します)。その後、すべてのスレッドがWebサービスを呼び出し、行の更新に戻ります。こんな感じです

List<Message> messages =getMessages(ThreadNO);//goes to DB

if (messages != null)
{
    foreach (Message bm in messages)
    {
        if (bm.Status)
        {
            try
            {
                bm.send();//calls Web service
            }
            catch (Exception ex)
            {
                LOG.Logger.Error(ex.ToString());
            }
            updateStatus(bm);//goes back to DB
        }
        else
        {
            if (bm.subscribe())
                updateSubscription(bm);//calls WS
            else
                updateUnsuccessfulSubscription(bm);//calls WS
        }
    }
}

DBの安価な方法でこれを実行したいと思います。DBに一度だけ行き、その後、オブジェクトメッセージからサブリストを作成したいと思います。その後、サブリストと同じ数のスレッドを作成し、それらのサブリストをsend()メソッドに渡します。各スレッドはsend()メソッドを呼び出します。しかし、すべてを終えたら、どうすればスレッドから抜け出し、ストアドプロシージャを1回だけ呼び出して更新することができますか(updateMessage()メソッド)?Webサービスを呼び出すためだけにスレッドを使用し、同時にスレッドからDbを呼び出す方法でこれを行うにはどうすればよいですか?

4

4 に答える 4

2

Parallel.ForEach()はあなたの場合に役立つと思います。

あなたがすることは、DBからリストを取得し、それを使用してアイテムを並行して処理し、Parallel.ForEach()それが完了したら、最後にデータベースを更新することです。

何かのようなもの:

var messages = GetAllMessages(); //goes to DB

Parallel.ForEach(
    messages,
    new ParallelOptions { MaxDegreeOfParallelism = threadCount },
    message => { /* your code that calls the web service */ });

UpdateAll(messages); // goes back to the DB

Parallel.ForEach()スレッドが使用されることを保証するものではありませんthreadCountが、あなたの場合、Webサービスを呼び出すとブロックされるため、すぐにその番号に到達する可能性があります。

于 2013-01-10T15:57:03.747 に答える
0

あなたの質問を完全に理解しているかどうかはわかりませんが、データベース呼び出しを一度に1つに制限したい場合は、lock:

// put this field in a class somewhere
static object gate = new object();

// then wrap all your database calls in locks:
lock( gate )
{
  updateStatus(bm);
}

そうすれば、データベースを同時に呼び出そうとするスレッドの数は関係ありません。一度に実行できる呼び出しは1つだけです。

于 2013-01-10T15:45:04.950 に答える
0

消費者/生産者のパターンを調べる必要があります。たとえば、http://en.wikipedia.org/wiki/Producer-consumer_problemを参照してください。

初期化によりDBにアクセスし、プロデューサー(それぞれ個別のスレッド)を起動します。これらはWebサービスを呼び出し、共有メモリ内データ構造(キュー)にステータスを記録します。

単一のコンシューマー(スレッド)が共有キュー内の要素を探し、それらをDBに保存して、キューから削除します。

于 2013-01-10T15:52:03.330 に答える
0

最初に、単一のスレッドで選択を行います

次に、スレッドを使用してメッセージのコレクションを調べます(Parallel.ForEachを使用します。独自のスレッドをロールするのに非常に手間がかかります)

これで、選択は更新を実行する方法から外れますが、単一のスレッドでも、他のタスクでデッドロックが発生する可能性があります。コードはそれを予期して処理する必要があります。

于 2013-01-10T16:00:32.840 に答える