您好,我在记录来自 Twitch.tv(视频流媒体平台)聊天机器人的消息时遇到了问题。
因此,简而言之,机器人是如何工作的:有一个静态方法Process
等待从服务器接收消息并创建一个任务来调用异步处理程序以选择消息的目标通道,添加到队列, Task.Run(() => SwitchMessage(buf)))
. 在其中,为所需的 Channel 实例调用了一个静态的Handler(message)
。一般理解*
现在问题来了。我写了记录器:
internal static class Logger
{
static readonly int timeHours = 24;
static string path = $"./logs/log{DateTime.Now.ToString().Replace(':','.')}.txt";
static FileStream stream = File.Open(path, FileMode.Append);
static Timer timerLogFile = new Timer(CreateNewLogFile, null, timeHours * 60 * 60000, timeHours * 60 * 60000);
public static void Write(string message)
{
if (string.IsNullOrEmpty(message))
return;
if(stream == null)
stream = File.Open(path, FileMode.Append);
var buf = Encoding.UTF8.GetBytes(DateTime.Now.ToString() + ": " + message + "\n");
stream.Write(buf, 0, buf.Length);
stream.Flush();
}
static void CreateNewLogFile(object obj)
{
path = $"./logs/log{DateTime.Now.ToString().Replace(':', '.')}.txt";
stream = File.Open(path, FileMode.Append);
}
}
private static void Process()
{
while (true)
{
try
{
string s = ircClient.ReadMessage();
if (s != null)
Task.Run(() => SwitchMessage(s));
Thread.Sleep(10);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
ShowLineMessage(ex.Message);
Console.ResetColor();
}
}
}
private static void SwitchMessage(string data)
{
try
{
Message currentMessage = new Message(data);
if(ViewChannel != null && currentMessage.Channel == ViewChannel.Name && currentMessage.Msg != null)
ShowLineMessage(currentMessage.UserName + ": " + currentMessage.Msg);
else if(!currentMessage.Success)
{
Console.ForegroundColor = ConsoleColor.Green;
ShowLineMessage(data);
Console.ResetColor();
lock (ErrorListMessages)
{
if (ErrorListMessages.Count > 50)
ErrorListMessages.Clear();
ErrorListMessages.Add(currentMessage);
}
return;
}
else if (currentMessage.UserName == "moobot" || currentMessage.UserName == "nightbot")
return;
if (currentMessage.Channel != null && Channels.ContainsKey(currentMessage.Channel))
{
Channels[currentMessage.Channel].Handler(currentMessage);
}
else
{
Channels.First().Value?.Handler(currentMessage);
}
}
catch(Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
ShowLineMessage(ex.Source + " " + ex.Message + " " + ex.Data);
Console.ResetColor();
return;
}
}
private void Handler(Message msg)
{
//...
SendMessage(message);
ShowLineMessage(message);
};
然后问题开始了。Console.WriteLine(...)
使用某种方法将输出替换为控制台:
public static void ShowLineMessage(string message)
{
Console.WriteLine(message);
Logger.Write(message);
}
这导致了这样一个事实,即随着消息流的增加,开始出现消息重复,从 2 到 6 次重复到控制台,并相应地记录到日志。我不知道那是什么...
ShowLineMessage
可以同时调用PS ,例如 100 个消息处理程序(这是很现实的)。操作系统是否会出现频繁调用静态方法的问题ShowLineMessage()
?请教如何是好?欢迎对代码提出批评和建议!谢谢!
这不是关于静态方法,而是关于使用来自不同线程
ShowLineMessage()
的非线程安全对象。FileStream
下面是关于线程安全的:
https://msdn.microsoft.com/en-us/library/system.io.filestream(v=vs.110).aspx
在某个并发容器中累积消息,假设累积了 1000 条消息,则替换另一个容器,然后从累积的容器中写入。
然而,
message
方法中的变量从何而来Handler
?