私のアプリには、TCP 接続を処理するためのスレッドがいくつかあります (1 つは読み取り用、もう 1 つは送信用、もう 1 つは新しい着信接続の処理用)。各スレッドは、すべてのクライアントに対して指定されたタイプの操作を処理するためTcpClient
、異なる IP で 5 つのインスタンスにデータを送信するとします。BlockingCollection
送信スレッドからアクセスしているだけでなく、送信するデータを生成する別のスレッドからもアクセスしているため、バッファとして使用しています。送信スレッドで実行される私の関数は次のようになります。
private void Sender()
{
while (run)
{
List<object[]> toRemove = new List<object[]>(); //bypass the fact that I cant remove a foreach iteration item from the BlockingCollection
foreach (object[] obj in sendBuffer.ToList())
{
string IP = obj[0].ToString();
string msg = obj[1].ToString();
byte[] data = Encoding.UTF8.GetBytes(msg);
foreach (TcpClient tcpc in TcpClients)
{
if ((tcpc.Client.RemoteEndPoint as IPEndPoint).Address.ToString() == IP)
{
NetworkStream stream = tcpc.GetStream();
stream.Write(data, 0, data.Length);
break;
}
}
toRemove.Add(obj);
}
for (int i = 0; i < toRemove.Count; i++) //the bypass mentioned above
{
object[] rmv = toRemove[i];
sendBuffer.TryTake(out rmv);
}
}
}
注:BlockingCollection
使用されるのは type<object[]>
です。私の問題は、トラフィックのある時点でバッファがいっぱいになり始めることです。バッファに最大 500 メッセージの制限を設定しましたが、これは簡単にオーバーフローします。今、私がそれを正しく理解していれば(よくわかりません)、TryTake
アイテムを削除しようとします。コレクションが現在使用されている場合は、待機して再試行します。(注: タイムアウトを 50 ミリ秒に設定してみました)。これが正しい場合 (そうでない場合は、誰かが私を修正して別の理由を提案してください)、問題はおそらく、TryTake
が呼び出されるほとんどの時間、コレクションがビジーであることです。それはありますか?はいの場合、どのように解決しますか?
コレクションの使用法については、データを生成するスレッドによって、コレクションは、1 ~ 80 アイテムの範囲を反復する foreach で 2 秒に約 1 回アクセスされます。約 20 個以上のアイテムでバッファに問題が発生し始めますが、それまでは問題ありません。送信者スレッドは現在、1 つのクライアントのみに送信しますが、後で最大 15 になります。したがって、ピーク時には、80 アイテム x 15 ユーザー = 約 2 秒あたり約 1200 アクセスになります。アドバイスをいただければ幸いです。