ユーザーが行ごとまたはバッチでログを記録できる単純なログフレームワークを作成しています。コード内のユーザー Write(message) と bool flushEveryLine (各行で true、バッチ書き込みで false) に基づいて、ログは flush() メソッドを呼び出すことによって書き込まれます。メッセージはメイン スレッドで作成され、ファイルに書き込まれると、outputConsole または DebugConsole は Task を使用して別のスレッドになります。リストは、TPL を使用してメイン スレッドとワーカー スレッド間で同期したいものです。そのため、TimerEvent が発生すると、失われたメッセージが出力に書き込まれます。問題はメッセージの変更です。以下のメッセージを参照してください。
protected virtual void Write(LogMessage message)
{
if (!this.IsEnabled) // log enabled or disabled.
return;
List<Task> list = new List<Task>();
foreach (Task task in _taskList)
{
if (task.Status != TaskStatus.RanToCompletion)
list.Add(task);
}
_taskList = list;
Task.WaitAll(_taskList.ToArray());
lock(storage)
{
//Add message to messages
**this.messages.Add(message);**
if (FlushEveryLine)
**Flush();**
}
public void Flush()
{
if (messages.Count == 0)
return;
_taskToMessagesMap.Add(counter, this.messages);
**Task.Factory.StartNew(() => FlushData(counter));**
++counter;
if (counter > 30000) // reset counter after large increment.
{
counter = 0;
}
this.messages.Clear();// clear the messages to record new set of messages before writing.
}
protected virtual void FlushData(int index)
{
**List<LogMessage> messages = _taskToMessagesMap[index];**
if (!IsEnabled) // logs enabled or not.
{
return;
}
lock (messages)
{
if (messages.Count == 0)
{
return;
}
IEnumerable<LogMessage> temp = messages.OrderBy(msg => msg.TimeStamp).ToArray();
this.flush(temp);
}
return;
}
コードの説明:: _taskToMessagesMap = new Dictionary (); // カウンタとメッセージのリストを格納する辞書。リストの動作をテストしたいので、これはハックです。
Task.Factory.StartNew(() => FlushData(カウンター)); //実際には、FlushData() が呼び出されたときに渡されたメッセージを使用する必要があるように、各スレッドに Flush(messages) を使用したいと考えています。しかし、ワーカー スレッドが実行されると、現在のメッセージ リストが使用されます。リストが参照渡しであることはわかっているため、この動作が見られますが、上記の例では整数でもこの動作が見られます。例: 私の辞書には 1 つのキー {0} とすべてのテスト メッセージしかありませんが、ワーカー スレッドに入るとキー 1 を探します。なぜですか? 整数パラメータは値渡しである必要があります。ワーカー スレッドを作成するときに、パラメーターとして 0 を渡しています。どうすればこれを修正できますか。
困っているので助けてください。