1.情景
想对外提供一个类库,但是这个类库是一个ui类型的,这就涉及到一个问题,调用这个接口的线程可能不是主线程(ui线程),而如果操作和控制ui(一般是)必须在主线程的。这时候如何能保证任何线程调用该接口都能切换到主线程呢。这就需要设置这个接口,无论任何接口的调用,最终控制ui的时候都自动切换到主线程。
有个问题,子线程不能控制ui,但是能创建winform吗,实验确认可以,但是控制winform中的ui必须在主线程
2.代码
2.1 工程概述
目标:创建两个winform,form1,form2。尝试在from1中调用form2的接口。
实验cace
情景 | form线程 | 使用对象 | 方式 | 结果 |
form1 中主线程控制form2的控件 | 主线程 | 成功 | ||
form1中子线程控制form2的控件 | 子线程 | form2 | 直接调用 | 失败 |
调用form2的setTextPost | 失败 | |||
form2.m_SyncContext | 成功 |
2.2 form1 代码
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 线程中创建winform
{
public partial class Form1 : Form
{
Form2 form2;
SynchronizationContext m_SyncContext = null;
public Form1()
{
InitializeComponent();
m_SyncContext = SynchronizationContext.Current;
}
//子线程创建form-间接SyncContext.Post
private void button1_Click(object sender, EventArgs e)
{
Task t = new Task(()=> {
form2 = new Form2();
form2.ShowDialog();// 使用这个可以,因为焦点在From1中。
//form2.Show();// 使用这个不可以,因为焦点不在From1中。
{
//这里写入失败
//form2.myTextBox1.Text = "线程中写数据-form2";
}
{
//这里写入会失败-因为不在u线程
//textBox1.Text = "线程中写数据-form1";
}
{
form2.setTextPost("线程中写数据-form2");
}
});
t.Start();
{
//这里
textBox1.Text = "线程中写数据-form1";
}
}
//-间接SyncContext.Post
private void button2_Click(object sender, EventArgs e)
{
//线程中直接更新可以
form2.setTextPost("线程中写数据-form2");
}
//主线程创建form
private void button3_Click(object sender, EventArgs e)
{
form2 = new Form2();
//form2.ShowDialog();
form2.Show();
{
//这里写入成功-因为在主线程
form2.myTextBox1.Text = "线程中写数据-form2";
}
{
//这里写入会成功-因为在主线程
textBox1.Text = "线程中写数据-form1";
}
}
//主线程创建form -利用SyncContext.post调用函数可以
private void button4_Click(object sender, EventArgs e)
{
form2 = new Form2();
//form2.ShowDialog();
form2.Show();
SynchronizationContext SyncContext = form2.m_SyncContext;
//这中可以
SyncContext.Post(form2.setText, "线程中写数据-form2");
}
}
}
2.3 from2 代码
using System.Threading;
using System.Windows.Forms;
namespace 线程中创建winform
{
public partial class Form2 : Form
{
public TextBox myTextBox1;
public SynchronizationContext m_SyncContext = null;
public Form2()
{
InitializeComponent();
m_SyncContext = SynchronizationContext.Current;
myTextBox1 = textBox1;
}
public void setText(object str) {
textBox1.Text = str.ToString();
}
public void setTextPost(string str) {
m_SyncContext.Post(setText, str);
}
}
}
3.运行效果