`

winform程序中如何跨线程修改控件的值

阅读更多

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);
}

 

分享到:
评论

相关推荐

    C#-WinForm跨线程修改UI界面的实例

    总结来说,C# WinForm应用中的跨线程修改UI是通过异步编程和UI线程同步机制来实现的。`Task`用于执行后台任务,`MethodInvoker`则帮助在主线程中安全地更新UI,确保程序的稳定性和正确性。这个实例提供了一个实用的...

    C#WinForm跨线程安全调用控件例程

    总结来说,C# WinForm应用程序中的跨线程安全调用控件是通过委托和适当的调用方法(如Invoke或BeginInvoke)来实现的。理解这些概念并正确使用,能够帮助开发者避免线程安全问题,同时保持程序的响应性和效率。在...

    跨线程访问winform控件

    综上所述,理解和掌握跨线程访问WinForm控件的方法是开发高效、稳定的多线程应用程序的关键。这不仅涉及到技术实现,还关系到程序的响应性和用户体验。在实际项目中,应根据具体情况选择合适的线程同步策略,以保证...

    Winform调用WPF控件

    在.NET框架中,Windows Forms(Winform)和...- 跨线程更新UI,确保在正确线程中刷新WPF控件。 通过以上步骤,我们可以成功地在Winform应用中嵌入并刷新WPF的DataGrid控件,享受到WPF的高级功能和Winform的兼容性。

    C#跨线程处理控件实例

    通过以上步骤,我们可以在不违反.NET Framework线程安全规则的情况下,实现跨线程更新Winform应用的UI控件。在这个打字游戏中,这种技术可以确保得分的实时更新,而不会影响游戏的流畅性或导致UI无响应。 总之,...

    C# Winform线程创建子窗体

    然而,跨线程操作主窗体的控件可能会引发`CrossThreadException`异常,因为Windows Forms控件只能在其创建的线程中被修改。为了解决这个问题,我们可以使用`Control.Invoke`或`Control.BeginInvoke`方法。这两个方法...

    C#之WinForm跨线程访问控件实例

    下面将详细讲解如何在C#的WinForm应用中实现跨线程访问控件。 首先,我们需要定义一个委托,这个委托类型将用于执行对控件的操作。在给定的例子中,我们创建了一个名为`InvokeDelegate`的无参数委托,它代表了不带...

    C#WinForm,多线程快速刷新界面。

    此外,还要注意避免UI控件的跨线程访问,因为这可能导致异常。正确的方式是在UI线程中更新UI控件。 总之,C# WinForm中利用多线程技术可以有效地解决界面快速刷新问题。通过合理地使用`Task`、`async/await`以及...

    WinForm后台线程与UI线程通讯

    在Windows Forms(WinForm)应用程序中,经常遇到需要在后台线程执行耗时操作,如数据处理、网络请求等,而这些操作的结果需要更新到用户界面(UI)上,例如显示进度条。由于.NET Framework的安全机制,直接在非UI...

    WinFormInvoke_winform多线程_防卡死_

    然而,由于.NET Framework的跨线程访问限制,工作线程不能直接修改UI控件的属性或调用其方法。此时,我们需要使用`Control.Invoke`或`Control.BeginInvoke`方法。这两个方法会在UI线程上下文中执行指定的委托,确保...

    c#多线程中子线程动态改变ui控件

    C#多线程中子线程动态改变UI控件 在桌面应用程序中,控制UI界面是一个非常重要的任务。特别是在C#多线程编程中,子线程更新UI控件是一个常见的问题。本文将总结C#子线程更新UI控件的方法,介绍两种常用的方法,以便...

    基于WinForm的多线程多进度条程序

    2. Invoke/BeginInvoke方法:当工作线程需要修改UI元素时,必须使用控件的Invoke或BeginInvoke方法,将操作委托到主线程执行,以避免跨线程访问引发的异常。 四、进度条控制 进度条(ProgressBar)控件在WinForm中...

    Winform实现多线程异步更新UI(进度及状态信息)

    3. **跨线程访问控件**:由于.NET Framework的安全机制,直接从非UI线程修改UI控件是不允许的。为了解决这个问题,可以使用控件的`Invoke`或`BeginInvoke`方法。这两个方法会在UI线程上执行传入的委托,从而安全地...

    WinForm下多线程配合Invoke函数ping百度实例。

    3. Invoke:确保非UI线程安全地更新UI元素,防止跨线程访问引发的异常。 综上所述,这个实例提供了关于如何在WinForm应用中有效利用多线程和Invoke方法的一个实际例子,对于理解和优化VB.NET应用程序的性能和用户...

    跨线程操作实例-Invoke()

    在C# Winform开发中,跨线程操作是常见的需求,特别是在UI界面与后台处理之间交互时。"跨线程操作实例-Invoke()"这个标题暗示了我们将在一个非UI线程(例如,后台线程)中修改UI元素,这是不被允许的,因为.NET ...

    .Net 多线程详解

    • 为什么Winform不允许跨线程修改UI线程控件的值 • 有没有什么办法可以简化WinForm多线程的开发 线程池 • 线程池的作用是什么? • 所有进程使用一个共享的线程池,还是每个进程使用独立的线程池? • 为什么...

    Unity3D与Winform交互

    在“Unity3D与Winform交互”这个主题中,我们主要探讨的是如何在Unity3D的场景中嵌入Winform控件,以及如何在Winform程序中调用Unity3D的功能。下面我们将深入探讨这两种交互方式: 1. **Unity3D Web与Winform交互*...

    C#下WINFORM和WINCE多线程编程

    - **后台线程更新UI**:使用Invoke或BeginInvoke方法在主线程中安全地更新UI控件,因为只有主线程可以修改UI元素。 - **Progress Bar和BackgroundWorker**:提供进度指示和异步操作支持,适合在多线程环境中使用。...

    winform的控件技巧

    在C#编程中,Windows Forms(Winform)是一个用于创建桌面应用程序的强大框架。它提供了丰富的控件库,使得开发者能够构建具有多种功能的用户界面。本文将深入探讨Winform控件的使用技巧,通过27个示例及源码,包括...

    C#WinForm多线程开发.pdf

    在WinForm应用中,直接跨线程操作UI控件会导致异常,因为在.NET 2.0之后,系统加强了线程安全检查。例如,尝试在非UI线程中修改UI元素(如`textBox1.Text`)会抛出“Cross-thread operation not valid”异常。 解决...

Global site tag (gtag.js) - Google Analytics