C# 登录到另一个进程

C# 登录到另一个进程,c#,performance,logging,client-server,ipc,C#,Performance,Logging,Client Server,Ipc,我有一个IIS服务器。该服务器获取web请求并为多个客户端执行一些计算。在这些计算中,有日志条目。这些日志条目使用一个标志,以便可以关闭它们。完全关闭日志条目会给我带来非常高的性能提升。或者换句话说,日志记录需要花费很多时间,但这是必要的,所以关闭它不是一种选择 我的想法是,我希望将日志条目推送到另一个进程,这样就可以让服务器的计算按需快速运行,并让另一个进程编写日志,从而在需要较少资源时让它编写日志 首先,我要问几个关于这个想法的问题。我的想法如下: 将日志字符串从服务器发送到另一个进程 将

我有一个IIS服务器。该服务器获取web请求并为多个客户端执行一些计算。在这些计算中,有日志条目。这些日志条目使用一个标志,以便可以关闭它们。完全关闭日志条目会给我带来非常高的性能提升。或者换句话说,日志记录需要花费很多时间,但这是必要的,所以关闭它不是一种选择

我的想法是,我希望将日志条目推送到另一个进程,这样就可以让服务器的计算按需快速运行,并让另一个进程编写日志,从而在需要较少资源时让它编写日志

首先,我要问几个关于这个想法的问题。我的想法如下:

  • 将日志字符串从服务器发送到另一个进程
  • 将日志字符串保存到日志进程中的队列中
  • 让日志进程定期在另一个线程中检查队列中的条目,如果有要写入的内容,则写入文件,然后休眠
  • 通过互斥限制对队列的访问以避免冲突
因此,首先的问题是,这能提高客户体验到的总体性能吗?还是只会产生一种开销,使问题恶化

现在,让我们更具体一些。

我在这个系统的第一个实现中使用了c#IpcChannel类。我还没有衡量实施是否更快,因为还有一些悬而未决的问题

我在IIS服务器中实现了IpcClient。我在另一个进程中启动IpcServer。然后我启动一个IIS客户端。因此,这里的三个过程是:

  • IpcServer
  • IIS服务器,实现IPCC客户端
  • IIS客户端应用程序
据我所知,沟通如下:

  • 用户在IIS客户端上调用某些函数
  • IIS客户端向IIS服务器发送webrequest
  • IIS服务器运行计算和日志,调用IPCLIENT方法
  • IPCLIENT方法被发送到IpcServer进程
  • IpcServer进程将日志stirng写入文件
现在来看看棘手的部分

我已经在IpcChannel中构建了一个调试日志,这意味着它每次检查队列中要写入实际日志的字符串时,都会将一行文本写入日志。停止IpcServer进程后,这将继续。我假设这会中断循环,但不知何故,所有这些都会继续进行,直到我关闭IIS服务器进程。这让我很困惑。如果没有IpcServer,假设日志实际上是由IpcServer进程完成的,我会假设调试日志会停止,但不会停止。知道这是为什么吗

根据上面提供的microsoft示例,以下是我的RemoteObject循环:

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace RemoteProcedureCall
{
    public class RemoteObject : MarshalByRefObject
    {
        const int MessageBuffer = 10;
        Queue<string> Messages = new Queue<string>();
        const string FilePath = "Test_Log.txt";
        const string DebugLogFilePath = "DebugLog.txt";
        Mutex QueueMutex = new Mutex(false, nameof(QueueMutex));
        private int callCount = 0;
        Thread WriterTask;

        public int GetCount()
        {
            Console.WriteLine("GetCount has been called.");
            callCount++;
            return (callCount);
        }

        #region Shortcuts

        /// <summary>
        /// Calls <see cref="File.AppendAllText(string, string)"/> using <see cref="FilePath"/>.
        /// </summary>
        /// <param name="text"></param>
        private void WriteLine(string text) => File.AppendAllText(FilePath, $"{text}{Environment.NewLine}");

        /// <summary>
        /// <see cref="WriteLine(string)"/> debug version
        /// </summary>
        /// <param name="text"></param>
        private void DebugConsole(string text) => File.AppendAllText(DebugLogFilePath, $"{text}{Environment.NewLine}");

        private void DequeueAndWriteMessage()
        {
            QueueMutex.WaitOne();
            if (Messages.Count != 0)
                WriteLine(Messages.Dequeue());
            QueueMutex.ReleaseMutex();
        }

        private void Flush()
        {
            DebugConsole($"------------------------------!!Flushing!!------------------------------");
            while (Messages.Count != 0)
                DequeueAndWriteMessage();
        }

        #endregion Shortcuts

        private void PrintMessagesTask()
        {
            DebugConsole($"Starting PrintMessagetast");
            try {
                while (true) {
                    DebugConsole($"Dequeue and write message in secondary thread");
                    DequeueAndWriteMessage();
                    if (Messages.Count < MessageBuffer) {
                        Thread.Sleep(5000);
                        DebugConsole("Thread.Sleep(5000);");
                    }
                    else {
                        Thread.Sleep(10);
                        DebugConsole("Thread.Sleep(10);");
                    }
                }
            }
            finally {
                Flush();
            }
        }

        /// <summary>
        /// Adds a Message to the <see cref="Messages"/> for them to later be posted to log file.
        /// </summary>
        /// <param name="text"></param>
        public void AddMessage(string text)
        {
            DebugConsole($"Enqueue Message");
            QueueMutex.WaitOne();

            Messages.Enqueue($"Enqueueing Message Nr. {GetCount()}:");
            Messages.Enqueue(text);

            QueueMutex.ReleaseMutex();
        }

        public void StartWriterThread()
        {
            DebugConsole($"Starting second thread");
            ThreadStart threadStart = new ThreadStart(PrintMessagesTask);
            WriterTask = new Thread(threadStart);
            WriterTask.Start();
            DebugConsole($"Started second thread");
        }

        public void AbortWriterThread()
        {
            WriterTask.Abort();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用系统线程;
命名空间RemoteProcedureCall
{
公共类远程对象:MarshalByRefObject
{
const int MessageBuffer=10;
队列消息=新队列();
const string FilePath=“Test_Log.txt”;
常量字符串DebugLogFilePath=“DebugLog.txt”;
Mutex QueueMutex=新的互斥(false,nameof(QueueMutex));
私有int callCount=0;
线程写入任务;
public int GetCount()
{
WriteLine(“GetCount已被调用。”);
callCount++;
返回(呼叫计数);
}
#区域快捷方式
/// 
///使用。
/// 
/// 
私有void WriteLine(string text)=>File.AppendAllText(FilePath,$“{text}{Environment.NewLine}”);
/// 
///调试版本
/// 
/// 
private void DebugConsole(string text)=>File.AppendAllText(DebugLogFilePath,$“{text}{Environment.NewLine}”);
私有无效出列和写入消息()
{
QueueMutex.WaitOne();
如果(Messages.Count!=0)
WriteLine(Messages.Dequeue());
QueueMutex.ReleaseMutex();
}
私有空间刷新()
{
调试控制台($“-----------------------------------!!刷新!!-----------------------------------”);
while(Messages.Count!=0)
退出队列并写入消息();
}
#端域快捷方式
私有void PrintMessagesTask()
{
调试控制台($“正在启动PrintMessagetast”);
试一试{
while(true){
DebugConsole($“在辅助线程中退出队列并写入消息”);
退出队列并写入消息();
if(Messages.Count
IIS服务器