winform程序是单线程的。
/// <summary>
/// 应用程序入口
/// </summary>
[STAThread]
static void Main() { }
而且对某一个控件来说,只有创建该控件的线程才能修改它的值。比如我们在设计器中拖到窗体上的控件,它们由程序的主线程创建,那么如果我们在执行中又创建了另外一个线程,那么我们在这个新创建的线程中无法直接修改窗体上控件的值。
有时候我们的winform程序在某一个处理上可能要会费大量的时间,这个时候我们可能会想用另一个线程来处理这个长时间的任务,而同时我 们可以做一些其它的事情。.net里面多线程异步处理可以使用ThreadPool.QueueUserWorkItem, BackgoundWorder等就可以非常简单地实现。就像上面图中显示的那样,在点击了按钮之后,我们希望异步地执行按钮的处理程序:
private void btnDoSomething_Click(object sender, EventArgs e)
{
WaitCallback callBack = new WaitCallback(DoSomething);
ThreadPool.QueueUserWorkItem(callBack, null);
}
private void DoSomething(object state)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
}
}
这里用Thread.Sleep(1000)来模拟了一个长时间的任务。到这里异步的目的已经达到,但是我们希望处理的同时能报告处理的进度,好给用户一些提示。比如例子中我们要更新一个进度条,可能会用如下的代码:
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
//can't do the cross-thread updating
reportProgress(i, 100);
}
private void ReportProgress(int countFinished, int total)
{
progressBar1.Maximum = total;
progressBar1.Value = countFinished;
}
我们希望可以在异步执行的线程中修改进度条控件的值,但是事与愿违。如果运行这段程序,.net会告诉我们“只有创建该控件的线程才可以修改该控件的值”, 这是线程的安全问题。但是我们确实是需要更新进度条的值怎么办呢?我们不能跨线程直接修改控件的值,但是我们可以通知控件的创建线程我们需要对某个控件进 行修改,让控件的创建线程去帮我们更新控件。“Control.Invoke(delegate,paras object[])”可以帮我们完成这一任务。
private void btnDoSomething_Click(object sender, EventArgs e)
{
WaitCallback callBack = new WaitCallback(DoSomething);
Object progressBar = progressBar1;
ThreadPool.QueueUserWorkItem(callBack, progressBar);
}
private void DoSomething(object state)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
//can't do the cross-thread updating
//reportProgress(i, 100);
ProgressBar pbar = state as ProgressBar;
if (pbar != null)
pbar.Invoke(reportProgress, new object[] { i, 100 });
}
}
我们调用了ProgressBar的Invoke方法通知该控件的创建线程修改它的值。Invoke方法有两个重载的版本:
public object Invoke(Delegate method);
public object Invoke(Delegate method, params object[] args);
这里使用了第二个,因为我们报告进度的方法需要参数。
public delegate void ReportTest(int countFinished, int total);
public FormTest()
{
InitializeComponent();
reportProgress = new ReportTest(ReportProgress);
// also can add
// reportProgress += new ReportTest(ReportProgress);
}
分享到:
相关推荐
跨线程访问winform控件;跨线程访问winform控件;跨线程访问winform控件
WinForm(C#)中跨线程访问控件的解决方法 由于多线程可能导致对控件访问的不一致,导致出现问题。C#中默认是要线程安全的,即在访问控件时需要首先判断是否跨线程,如果是跨线程的直接访问,在运行时会抛出异常。 ...
C# 跨线程调用控件经常报错,提供一种标准的跨新城调用控件的方法
多个线程竞争读写同一个资源往往会造成意想不到的意外结果,UI界面也是一种资源,所以跨线程修改UI界面往往被加以限制。这里采用Task + MethodInvoker的方式完成跨线程对UI对的修改。
开发.Net的WinForm程序时,常常遇到需要在一个线程中访问另一个线程创建的控件的情况,这个工具类用静态函数的形式,将相关代码封装,使得调用控件时可以不用考虑线程一致性。
线程间操作无效: 从不是创建控件的线程访问它。当我们执行C#程序出现此错误提示时,可以采用委托的方法来解决,但是有个重要问题需要注意...本例程提供了跨线程安全调用控件的方法。
解决winform编程中使用线程界面卡死的案例 用了委托
使用delegate和Invoke,使用delegate和BeginInvoke,使用BackgroundWorker组件,使用SynchronizationContext组件
关于winform使用timer进行多线程操作的例子 一个关于网段ping的例子 很好的解释了system.timers.timer的用法
其中分页控件简洁高效,支持多线程的跨线程安全访问,是开发数据展示软件的优秀分页控件。 二、功能介绍 1、WinForm程序在使用DataGridView显示数据时,通常需要分页。一个好的分页控件应当简洁高效且功能强大(如...
WinForm程序设计_高级控件讲述C#中的一些高级控件图treeView、listView等
1、winform项目中跨线程访问控件: 编写一个Winform小实例:在做winform项目中,有时为了将系统运行的状态实时显示到Form中,因此添加一个RichTextbox控件实时显示系统运行日志。本例实现的操作是将日志以字符串的...
winForm皮肤&控件winForm皮肤&控件winForm皮肤&控件winForm皮肤&控件
主要介绍了C#之WinForm跨线程访问控件,实例讲述了跨线程访问控件的简单实现方法与用法,需要的朋友可以参考下
Winform调用WPF控件,演示WPF的DataGrid控件在Winform中如何调用刷新
winform的自定义控件,可以在设计时选择资源窗口
在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应, 同时我们又需要在工作线程中更新UI界面上的控件。但直接访问会出现“线程间操作无效”的情况,因为.NET禁止了跨线程调用控件, 否则...
在WinForm里面有时候需要清空自己输入内容或是选择的选项,以便重新操作流程,那么一般你是怎么清空界面各个控件值的呢?如果窗体里面控件,尤其是TextBox控件比较多的时候,代码里面是不是要设置每个控件的Text属性...
winform多线程更新控件
c# winform 一个好用的打印控件,我的博客有代码