richtexbox 如何从 winforms 上的事件侦听器附加文本异步?
How richtexbox can append text async from event listener on winforms?
如何异步使用richtextbox?例如,我有一个 class 和一个记录某种计算的事件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//I subscribe to an event that often sends messages
//and I want to display
var c = new Core();
c.Notify += DisplayMessage;
c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{ //When a event arrives, transfer to richTextBox1
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
//
public void ExampleMethod()
{
//generate messages with a pause in a random value
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 2000);
Thread.Sleep(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
} //The class in which log messages are placed
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
//Extension method to set line colors in RichTextBox
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
尝试了 backgroundworker、task、synchronization... 的选项,但没有结果。我很惊讶 WinForms 已经存在了很多年,而 Microsoft 还没有向它们添加异步操作,例如 AppendTextAsync()
。如何强制将文本异步添加到 richtextbox?
在您的表单上添加另一个文本框
将此代码粘贴到 Form1.cs 中所有内容的顶部:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
var c = new Core();
c.Notify += DisplayMessage;
await c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
public async Task ExampleMethod()
{
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 200);
await Task.Delay(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
}
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
运行 它,单击按钮,然后在另一个文本框中继续输入 - 它保持响应等等。我不知道你需要等多久才能看到主要的减速,因为RTB 中的文本变得很大。但实际上您应该定期查看日志,这样您就不会在 RTB
中建立兆字节的文本
winforms 中的异步不是让控件使用某种异步方式进行更新;控件只能由创建它们的线程访问,因此与控件的任何交互我们通常要求该线程执行它(但我认为这是一个角度问题:如果后台线程要求 UI 线程更新一个控件然后它被异步完成后台线程正在做的任何工作) - 确保你对它们所做的访问是快速的,做你的繁重工作(API 调用?)使用异步方式然后调用以获取你的UI 更新控件的线程。
如何异步使用richtextbox?例如,我有一个 class 和一个记录某种计算的事件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//I subscribe to an event that often sends messages
//and I want to display
var c = new Core();
c.Notify += DisplayMessage;
c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{ //When a event arrives, transfer to richTextBox1
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
//
public void ExampleMethod()
{
//generate messages with a pause in a random value
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 2000);
Thread.Sleep(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
} //The class in which log messages are placed
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
//Extension method to set line colors in RichTextBox
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
尝试了 backgroundworker、task、synchronization... 的选项,但没有结果。我很惊讶 WinForms 已经存在了很多年,而 Microsoft 还没有向它们添加异步操作,例如 AppendTextAsync()
。如何强制将文本异步添加到 richtextbox?
在您的表单上添加另一个文本框
将此代码粘贴到 Form1.cs 中所有内容的顶部:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ExampleProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
var c = new Core();
c.Notify += DisplayMessage;
await c.ExampleMethod();
}
private void DisplayMessage(object sender, LogEventArgs e)
{
richTextBox1.AppendText("\r\n" + e.Date.ToString("dd/MM/yyyy HH:mm:ss "), Color.SlateGray);
richTextBox1.AppendText(e.Message, Color.Blue);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
class Core
{
public delegate void LogHandler(object sender, LogEventArgs e);
public event LogHandler Notify;
public async Task ExampleMethod()
{
var rand = new Random();
for (int i = 1; i < 10000; i++)
{ var pause = rand.Next(50, 200);
await Task.Delay(pause);
Notify?.Invoke(this, new LogEventArgs($"logged {i} pause in miliseconds {pause}", DateTime.Now, MessageType.Notice));
}
}
}
class LogEventArgs
{
public string Message { get; }
public DateTime Date { get; }
public MessageType MessageType { get; }
public LogEventArgs(string mes, DateTime date, MessageType messageType)
{
Message = mes;
Date = date;
MessageType = messageType;
}
}
enum MessageType
{
Notice,
Warning,
Error,
}
public static class RichTextBoxExtensions
{
public static void AppendText(this RichTextBox box, string text, Color color)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
box.SelectionColor = color;
box.AppendText(text);
box.SelectionColor = box.ForeColor;
}
}
}
运行 它,单击按钮,然后在另一个文本框中继续输入 - 它保持响应等等。我不知道你需要等多久才能看到主要的减速,因为RTB 中的文本变得很大。但实际上您应该定期查看日志,这样您就不会在 RTB
中建立兆字节的文本winforms 中的异步不是让控件使用某种异步方式进行更新;控件只能由创建它们的线程访问,因此与控件的任何交互我们通常要求该线程执行它(但我认为这是一个角度问题:如果后台线程要求 UI 线程更新一个控件然后它被异步完成后台线程正在做的任何工作) - 确保你对它们所做的访问是快速的,做你的繁重工作(API 调用?)使用异步方式然后调用以获取你的UI 更新控件的线程。