线程间操作无效: 从不是创建控件的线程访问它的三种解决方法
转载请标明出处:Python Excellent的博客
线程的3种创建方式:
1、Task.Factory.StartNew(() => );
private void uiButton1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => Test1());
}
2、new Task(() =>{});
private void uiButton2_Click(object sender, EventArgs e)
{
Task task2 = new Task(() =>
{
Test2();
});
task2.Start();
}
3、new Thread();
- 此为最基础方法 (入门级)
private void uiButton3_Click(object sender, EventArgs e)
{
//方式1:
Thread TestThread = new Thread(Test1);
TestThread.IsBackground = true;
TestThread.Start();
//方式2:
Thread thread1 = new Thread(new ThreadStart(Test1))
{
IsBackground = true
};
thread1.Start();
}
方法一:异步委托线程中控件访问
- 运行效果如图所示
* 先在按钮事件中创建一个Test1()线程* 在测试1中有两种方法可以访问窗体线程(首推荐)
private void uiButton1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => Test1());
}
public void Test1()
{
//创建了一个异步委托线程
//第一种方法 (推荐)
this.BeginInvoke((MethodInvoker)delegate
{
try
{
label1.Text = "方法1.1 列举测试";
MessageBox.Show("创建线程访问UI线程已完成");
}
catch (Exception ex)
{ }
});
//第二种方法 (推荐)
this.Invoke(new EventHandler(delegate
{
try
{
label2.Text = "方法1.2 列举测试";
MessageBox.Show("创建线程访问UI线程已完成");
}
catch (Exception)
{}
}));
}
方法二:采用不同步的自由线程上下文的基类
- public SynchronizationContext UiContext //第一步全局声明
- UiContext = SynchronizationContext.Current; //第二部在public Form1()中实例化该对象即可
public SynchronizationContext UiContext ;//UI主线程上下文
public Form1()
{
InitializeComponent();
//方式二:实例化一个获取当前UI主线程上下文对象。
UiContext = SynchronizationContext.Current;
}
private void uiButton2_Click(object sender, EventArgs e)
{
Task task2 = new Task(() =>
{
Test2();
});
task2.Start();
}
public void Test2()
{
try
{
Thread.Sleep(200);
UiContext.Post(e =>
{
label1.Text = "方法二列举测试";
MessageBox.Show("创建线程访问UI线程已完成");
}, 0);
}
catch (Exception)
{
throw;
}
}
方法三:取消跨线程访问(不推荐)
** 取消跨线程访问(此为不安全操作)**
- Control.CheckForIllegalCrossThreadCalls = false; //在 public Form1() 函数或 Form1_Load() 中声明此代码即可
public Form1()
{
InitializeComponent();
//方式三:取消跨线程访问(不安全操作)
Control.CheckForIllegalCrossThreadCalls = false;
}
//按钮点击事件创建线程并开启线程
private void uiButton1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ThreadStart(Test))
{
IsBackground = true
};
thread1.Start();
}
public void Test()
{
try
{
Thread.Sleep(200);
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);// 1s间隔显示
//在线程间访问操作窗体控件
label1.Text = String.Format("这是第{0}次举例测试", i);
}
//在线程间访问操作窗体控件
MessageBox.Show("创建线程访问UI线程已完成");
}
catch (Exception)
{
throw;
}
}