Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将信息记录到窗口文本框_C#_Multithreading_Textbox_Window_Invoke - Fatal编程技术网

C# 将信息记录到窗口文本框

C# 将信息记录到窗口文本框,c#,multithreading,textbox,window,invoke,C#,Multithreading,Textbox,Window,Invoke,我正在将一个控制台应用程序转换为窗口格式,作为一个对它知之甚少但在过去有过类似窗口格式应用程序经验的人,我认为这不会太难 因此,我创建了一个表单,并在其中添加了一个文本框,以获取日志信息 这个控制台应用程序过去是在一个线程中运行的,后来我添加了第二个线程,以允许窗体与控制台并排运行以进行测试。(奇怪的是,它现在在单线程中运行良好) 这是我用来向表单中写入文本的代码,只是我在表单上没有得到任何东西 static Form1 f = new Form1(); delegate voi

我正在将一个控制台应用程序转换为窗口格式,作为一个对它知之甚少但在过去有过类似窗口格式应用程序经验的人,我认为这不会太难

因此,我创建了一个表单,并在其中添加了一个文本框,以获取日志信息

这个控制台应用程序过去是在一个线程中运行的,后来我添加了第二个线程,以允许窗体与控制台并排运行以进行测试。(奇怪的是,它现在在单线程中运行良好)

这是我用来向表单中写入文本的代码,只是我在表单上没有得到任何东西

    static Form1 f = new Form1();
    delegate void SetTextCallback(string s);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (f.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            f.textBox1.Invoke(d, new object[] { text });
        }
        else
        {
            f.textBox1.AppendText(text);
        }
    }
我可以确认有文本输入“text”变量,但它没有进入表单

    static Form1 f = new Form1();
    delegate void SetTextCallback(string s);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (f.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            f.textBox1.Invoke(d, new object[] { text });
        }
        else
        {
            f.textBox1.AppendText(text);
        }
    }
任何帮助都将不胜感激

这是完整的文件:

using System;
using System.Windows.Forms;
using Chraft.Properties;
using System.IO;
using Chraft.Plugins.Events.Args;
using Chraft.Plugins.Events;

namespace Chraft
{
public class Logger
{
    private StreamWriter WriteLog;
    private Server Server;

    internal Logger(Server server, string file)
    {
        Server = server;
        try
        {
            WriteLog = new StreamWriter(file, true);
            WriteLog.AutoFlush = true;
        }
        catch
        {
            WriteLog = null;
        }
    }

    ~Logger()
    {
        try
        {
            WriteLog.Close();
        }
        catch
        {
        }
    }

    public void Log(LogLevel level, string format, params object[] arguments)
    {
        Log(level, string.Format(format, arguments));
    }

    public void Log(LogLevel level, string message)
    {
        //Event
        LoggerEventArgs e = new LoggerEventArgs(this, level, message);
        Server.PluginManager.CallEvent(Event.LOGGER_LOG, e);
        if (e.EventCanceled) return;
        level = e.LogLevel;
        message = e.LogMessage;
        //End Event

        LogToConsole(level, message);
        LogToForm(level, message);
        LogToFile(level, message);
    }

    private void LogToConsole(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            Console.WriteLine(Settings.Default.LogConsoleFormat, DateTime.Now, level.ToString().ToUpper(), message);
        }
    }
    static Form1 f = new Form1();
    delegate void SetTextCallback(string s);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (f.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            f.textBox1.Invoke(d, new object[] { text });
        }
        else
        {
            f.textBox1.AppendText(text);
        }
    }

    private void LogToForm(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            SetText(DateTime.Now + level.ToString().ToUpper() + message);
        }
    }

    private void LogToFile(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogFileLevel && WriteLog != null)
            WriteLog.WriteLine(Settings.Default.LogFileFormat, DateTime.Now, level.ToString().ToUpper(), message);
    }

    public void Log(Exception ex)
    {
        //Event
        LoggerEventArgs e = new LoggerEventArgs(this, LogLevel.Debug, ex.ToString(), ex);
        Server.PluginManager.CallEvent(Event.LOGGER_LOG, e);
        if (e.EventCanceled) return;
        //End Event

        Log(LogLevel.Debug, ex.ToString());
    }


    public enum LogLevel : int
    {
        Trivial = -1,
        Debug = 0,
        Info = 1,
        Warning = 2,
        Caution = 3,
        Notice = 4,
        Error = 5,
        Fatal = 6
    }
}
}

问题是您正在创建两个表单对象。在Program.cs文件中创建的一个: Application.Run(新Form1())

以及您在logger类中创建的

表格f=新表格1()

传递给Application.Run的是用户正在与之交互的。由于Application.Run调用,它变得可见并响应用户交互

您在logger类上创建的那个就在内存中。它的文本框很高兴地添加了你要求它输入的文本,但是这个文本框在任何地方都看不见

处理这种情况有很多方法。您可以通过Application.OpenForms访问正确的表单对象,但更合适的处理方法是在记录器上添加一个表单可以订阅的事件,并可以处理更新文本框以响应该事件

已更新

class LoggerLogEventArgs : EventArgs
{
    public LoggerLogEventArgs(string message)
    {
        this.message = message;
    }
    private string message;
    public string Message { get { return message; } }
}

class Logger
{
    public event EventHandler<LoggerLogEventArgs> Logged;

    protected virtual void OnLogged(LoggerLogEventArgs e)
    {
        EventHandler<LoggerLogEventArgs> handler = Logged;
        if (handler != null)
            handler(this, e);
    }

    // I would change this method name to LogToEvent
    private void LogToForm(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            OnLogged(new LoggerLogEventArgs(message));
        }
    }
}

class Form1 : Form
{
    // Subscribe to the logger only when we are ready to display text
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        GetLog().Logged += new EventHandler<LoggerLogEventArgs>(logger_Logged);
    }

    // Unsubscribe from the logger before we are no longer ready to display text
    protected override void OnHandleDestroyed(EventArgs e)
    {
        GetLog().Logged -= new EventHandler<LoggerLogEventArgs>(logger_Logged);
        base.OnHandleDestroyed(e);
    }

    private void logger_Logged(object sender, LoggerLogEventArgs e)
    {
        if (InvokeRequired)
            BeginInvoke(new EventHandler<LoggerLogEventArgs>(logger_Logged), e);
        else
            textBox1.AppendText(e.Message);
    }
}
类LoggerLogEventArgs:EventArgs
{
公共LoggerLogEventArgs(字符串消息)
{
this.message=消息;
}
私有字符串消息;
公共字符串消息{get{return Message;}}
}
类记录器
{
记录公共事件事件处理程序;
受保护的虚拟void OnLogged(LoggerLogEventArgs e)
{
EventHandler=已记录;
if(处理程序!=null)
处理者(本,e);
}
//我会将此方法名称更改为LogToEvent
专用void日志格式(日志级别,字符串消息)
{
如果((int)级别>=Settings.Default.LogConsoleLevel)
{
OnLogged(新的LoggerLogEventArgs(消息));
}
}
}
类别表格1:表格
{
//仅当我们准备好显示文本时,才订阅记录器
已创建受保护的重写无效OnHandleCreated(EventArgs e)
{
碱基。根据HandleCreated(e);
GetLog().Logged+=新的事件处理程序(logger\u Logged);
}
//在我们不再准备显示文本之前,取消从日志记录器的订阅
受保护的覆盖无效OnHandleDestroyed(事件参数e)
{
GetLog().Logged-=新的事件处理程序(logger\u Logged);
碱基。经处理的雌雄同体(e);
}
已记录私有无效记录器(对象发送器、LoggerLogEventArgs e)
{
如果(需要调用)
BeginInvoke(新的事件处理程序(日志记录程序),e);
其他的
textBox1.AppendText(e.Message);
}
}

问题在于您正在创建两个表单对象。在Program.cs文件中创建的一个: Application.Run(新Form1())

以及您在logger类中创建的

表格f=新表格1()

传递给Application.Run的是用户正在与之交互的。由于Application.Run调用,它变得可见并响应用户交互

您在logger类上创建的那个就在内存中。它的文本框很高兴地添加了你要求它输入的文本,但是这个文本框在任何地方都看不见

处理这种情况有很多方法。您可以通过Application.OpenForms访问正确的表单对象,但更合适的处理方法是在记录器上添加一个表单可以订阅的事件,并可以处理更新文本框以响应该事件

已更新

class LoggerLogEventArgs : EventArgs
{
    public LoggerLogEventArgs(string message)
    {
        this.message = message;
    }
    private string message;
    public string Message { get { return message; } }
}

class Logger
{
    public event EventHandler<LoggerLogEventArgs> Logged;

    protected virtual void OnLogged(LoggerLogEventArgs e)
    {
        EventHandler<LoggerLogEventArgs> handler = Logged;
        if (handler != null)
            handler(this, e);
    }

    // I would change this method name to LogToEvent
    private void LogToForm(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            OnLogged(new LoggerLogEventArgs(message));
        }
    }
}

class Form1 : Form
{
    // Subscribe to the logger only when we are ready to display text
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        GetLog().Logged += new EventHandler<LoggerLogEventArgs>(logger_Logged);
    }

    // Unsubscribe from the logger before we are no longer ready to display text
    protected override void OnHandleDestroyed(EventArgs e)
    {
        GetLog().Logged -= new EventHandler<LoggerLogEventArgs>(logger_Logged);
        base.OnHandleDestroyed(e);
    }

    private void logger_Logged(object sender, LoggerLogEventArgs e)
    {
        if (InvokeRequired)
            BeginInvoke(new EventHandler<LoggerLogEventArgs>(logger_Logged), e);
        else
            textBox1.AppendText(e.Message);
    }
}
类LoggerLogEventArgs:EventArgs
{
公共LoggerLogEventArgs(字符串消息)
{
this.message=消息;
}
私有字符串消息;
公共字符串消息{get{return Message;}}
}
类记录器
{
记录公共事件事件处理程序;
受保护的虚拟void OnLogged(LoggerLogEventArgs e)
{
EventHandler=已记录;
if(处理程序!=null)
处理者(本,e);
}
//我会将此方法名称更改为LogToEvent
专用void日志格式(日志级别,字符串消息)
{
如果((int)级别>=Settings.Default.LogConsoleLevel)
{
OnLogged(新的LoggerLogEventArgs(消息));
}
}
}
类别表格1:表格
{
//仅当我们准备好显示文本时,才订阅记录器
已创建受保护的重写无效OnHandleCreated(EventArgs e)
{
碱基。根据HandleCreated(e);
GetLog().Logged+=新的事件处理程序(logger\u Logged);
}
//在我们不再准备显示文本之前,取消从日志记录器的订阅
受保护的覆盖无效OnHandleDestroyed(事件参数e)
{
GetLog().Logged-=新的事件处理程序(logger\u Logged);
碱基。经处理的雌雄同体(e);
}
已记录私有无效记录器(对象发送器、LoggerLogEventArgs e)
{
如果(需要调用)
BeginInvoke(新的事件处理程序(日志记录程序),e);
其他的
textBox1.AppendText(e.Message);
}
}

我正在与主程序文件不同的日志文件中运行代码。它目前登录到控制台没有问题,我将在上面添加代码。我正在主程序文件的另一个日志文件中运行代码。它目前登录到控制台没有问题,我将在上面添加代码。我在实现一个工作版本时遇到了一些困难,你有一些示例代码我可以用来重新编码吗?我