关于 Invoke、Invokerequired 和多线程的 C# 问题
C# Questions regarding Invoke, Invokerequired & Multithreading
我在不同的线程上有 2 个表单 运行。 Form2 将生成一个字符串,将其发送回 form1 并更新 form1 中的 richtextbox。我从朋友那里得到了代码,但我不明白其中的一部分。
能否请您向我解释一下为什么我们需要条件:
if (this.f1_rtb_01.InvokeRequired) { }
下面两行是做什么的?
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
完整代码表 1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace PassingData2Forms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string str_1;
private void call_form_2()
{
for (int i = 0; i < 10; i++)
{
Form2 inst_form2 = new Form2();
inst_form2.ShowDialog();
string result = inst_form2.SelectedString;
this.SetText(result);
}
}
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.f1_rtb_01.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
if (text != "")
{
this.f1_rtb_01.AppendText(text + Environment.NewLine);
}
else
{
this.f1_rtb_01.AppendText("N/A" + Environment.NewLine);
}
}
}
private void f1_but_01_Click(object sender, EventArgs e)
{
Thread extra_thread_01 = new Thread(() => call_form_2());
extra_thread_01.Start();
}
}
}
每个表单在不同的线程上运行。让我们称它们为 thread1 和 thread2。由于您想从线程 1 更新线程 2 上的某些内容,因此您需要让这两个线程相互通信。这就是 invoke
的工作
条件是检查是否需要调用。如果您在 thread1 本身上更新 thread1 中的字符串,则不需要调用,否则它是。
这部分:
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
使当前表单调用 SetTextCallback
委托的实例,将变量 text
作为参数传递。委托实例指向 SetText()
方法,由于调用 this.Invoke()
,该方法将在与表单相同的线程上执行。
调用用于将代码的执行从后台线程转移到窗体s/control的线程,从而使执行线程安全。
这部分只是为了检查您是否需要调用:
if (this.f1_rtb_01.InvokeRequired)
如果您不需要调用,则意味着代码已经在窗体或控件的线程上运行,如果您尝试调用,将会抛出异常。
我在不同的线程上有 2 个表单 运行。 Form2 将生成一个字符串,将其发送回 form1 并更新 form1 中的 richtextbox。我从朋友那里得到了代码,但我不明白其中的一部分。
能否请您向我解释一下为什么我们需要条件:
if (this.f1_rtb_01.InvokeRequired) { }
下面两行是做什么的?
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
完整代码表 1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace PassingData2Forms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string str_1;
private void call_form_2()
{
for (int i = 0; i < 10; i++)
{
Form2 inst_form2 = new Form2();
inst_form2.ShowDialog();
string result = inst_form2.SelectedString;
this.SetText(result);
}
}
delegate void SetTextCallback(string text);
private void SetText(string text)
{
if (this.f1_rtb_01.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
if (text != "")
{
this.f1_rtb_01.AppendText(text + Environment.NewLine);
}
else
{
this.f1_rtb_01.AppendText("N/A" + Environment.NewLine);
}
}
}
private void f1_but_01_Click(object sender, EventArgs e)
{
Thread extra_thread_01 = new Thread(() => call_form_2());
extra_thread_01.Start();
}
}
}
每个表单在不同的线程上运行。让我们称它们为 thread1 和 thread2。由于您想从线程 1 更新线程 2 上的某些内容,因此您需要让这两个线程相互通信。这就是 invoke
的工作
条件是检查是否需要调用。如果您在 thread1 本身上更新 thread1 中的字符串,则不需要调用,否则它是。
这部分:
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
使当前表单调用 SetTextCallback
委托的实例,将变量 text
作为参数传递。委托实例指向 SetText()
方法,由于调用 this.Invoke()
,该方法将在与表单相同的线程上执行。
调用用于将代码的执行从后台线程转移到窗体s/control的线程,从而使执行线程安全。
这部分只是为了检查您是否需要调用:
if (this.f1_rtb_01.InvokeRequired)
如果您不需要调用,则意味着代码已经在窗体或控件的线程上运行,如果您尝试调用,将会抛出异常。