C# 从线程调用可以工作,但可以';做起来不简单吗?
我设法制作了一个简单的程序,从不同的线程和类更新文本框。以视觉方式学习线程的最简单方法。;) 代码由msdn提供的文档编制而成。它运行,我看不到内存泄漏。但我觉得这可以做得更简单 主要有两类;表单和背景类。后台类中有一个名为generateStream的函数,该函数通过对名为updateTextBox的函数的委托来更新Form类中的文本框 按下按钮开始时,将执行两个操作。直接调用First generateStream。当generateStream就绪时,将生成一个线程,该线程将再次运行generateStream(通过函数)。当使用不同的线程时,TextBox需要调用解决方案 所有这些都得到了实施并发挥了作用。我认为这是相当多的代码,也许可以做得更干净 main类中更新表单并被回调的函数C# 从线程调用可以工作,但可以';做起来不简单吗?,c#,multithreading,forms,C#,Multithreading,Forms,我设法制作了一个简单的程序,从不同的线程和类更新文本框。以视觉方式学习线程的最简单方法。;) 代码由msdn提供的文档编制而成。它运行,我看不到内存泄漏。但我觉得这可以做得更简单 主要有两类;表单和背景类。后台类中有一个名为generateStream的函数,该函数通过对名为updateTextBox的函数的委托来更新Form类中的文本框 按下按钮开始时,将执行两个操作。直接调用First generateStream。当generateStream就绪时,将生成一个线程,该线程将再次运行gen
public void updateTextBox(string strtext)
{
if (this.InvokeRequired) //When calling from another thread; invoke is required.
{
SetTextCallBack cb = new SetTextCallBack(updateTextBox);
this.Invoke(cb, new object[] { strtext });
}
else //Call can be performed safely.
{
textBoxStatus.SelectionStart = textBoxStatus.Text.Length;
textBoxStatus.AppendText(strtext);
textBoxStatus.Update();
}
}
通过单击按钮完成的操作
private void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
/*
* Step 1: Let's call the function blocking.
* The GUI will not respond to mouse geastures. Hoover mouse over inputbox to see no change in pointer.
*/
bg.generateStream(numberOfCalls, "GUI Thread: ");
/*
* Step 2: Let's call the function in a seperate thread.
* The GUI will now respond to the mouse. Hoover mouse over inputbox to see pointer change.
*/
Thread sepThread = new Thread(new ThreadStart(this.TheFunction));
sepThread.Start();
buttonStart.Enabled = true;
}
后台类中的generateStream函数
public void generateStream(int amountOfStreams, string inpString)
{
for (int i = 0; i < amountOfStreams; i++)
{
Thread.Sleep(1000); //Easy does it.
myCallBack(inpString + i.ToString() + System.Environment.NewLine); //This is the text to the Main Form.
}
}
public void generateStream(int-amountOfStreams,string-inpString)
{
对于(int i=0;i
使用线程时,我现在使用两个回调来更新文本框。一个是从后台类到表单,另一个是实现调用。例如,是否没有信号量解决方案可以使我的updateTextBox函数只能有一个线程访问?当InvokeRequest为true时调用Invoke没有什么害处。我还喜欢在C#2.0中使用匿名方法。您可以按如下方式简化功能:
private delegate void SimpleProc();
private void updateTextBox(string strtext) {
this.Invoke(new SimpleProc(delegate() {
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.AppendText(strtext);
textBox1.Update(); // only needed if updateTextBox is called from UI thread
}), null);
}
将Invoke替换为BeginInvoke对于fire-and-forget场景非常有用,在这种场景中,您不希望后台线程等待UI线程完成更新,但您需要确定这是否适合您的应用程序
更新后的函数可以直接从UI线程或后台线程调用。不需要回调;使用的唯一回调函数是updateTextBox中的匿名函数。没有比这更简单的了。事实上,这很简单,在很多情况下不需要创建单独的函数来调用UI线程。我不太明白你的问题是什么,你能试着改写你的最后一段来更好地解释你的问题是什么吗。你是对的,它太多文本,没有方向。作为提示,你的主要问题
我认为这是相当多的代码,也许可以做得更干净。
应该放在文章的底部而不是中间,这样也可以很容易找到。我强烈推荐文章“”。您的最后一个问题是,例如,是否没有信号量解决方案可以使我的updateTextBox函数只能有一个线程访问权限?与此相反。我在上一篇评论中强调的那句话是“目标不是步骤”的完美例子,谢谢!这已经省去了if语句的需要,并且使它变得更简单。我所付出的唯一代价就是总是执行额外的回调。我在想信号灯之类的东西。但直到现在,我才发现调用是处理这个问题的正确方法。实际上,如果您从UI线程进行调用,Invoke基本上会执行原始代码所做的操作,即直接调用回调,而不向消息队列发送任何消息。在这种情况下,性能影响可以忽略不计;调用只涉及一些额外的函数调用和隐藏的代码。我猜回调中实际更新UI的代码需要花费更多的时间。如果从工作线程调用Invoke,则会将自定义窗口消息发布到消息队列,以便在将来某个时候由UI线程处理。