c#通过线程来控制进度条(转)--讲解多线程对界面的操作

莫水千流 莫水千流     2022-08-05     228

关键词:

// 通过创建委托解决传递参数问题
private void _btnRun_Click( object sender, System.EventArgs e )
{
RunTaskDelegate runTask = new RunTaskDelegate( RunTask );

// 委托同步调用方式
runTask( Convert.ToInt16( _txtSecond.Value ) );
}

//通过创建委托解决传递参数问题,通过委托的异步调用消除用户界面线程的阻塞问题
private void _btnRun_Click( object sender, System.EventArgs e )
{
RunTaskDelegate runTask = new RunTaskDelegate( RunTask );

// 委托异步调用方式
runTask.BeginInvoke( Convert.ToInt16( _txtSecond.Value ), null, null );
}

多线程安全

到这里为止,我们已经解决了长任务的难题和传递参数的困扰。但是我们真的解决了全部问题吗?回答是否定的。

我们知道 Windows 编程中有一个必须遵守的原则,那就是在一个窗体创建线程之外的任何线程中都不允许操作窗体。

我们上面的程序就是存在这样的问题:工作线程是在 ShowProgress 方法中修改了用户界面的进度条的属性。那为什么程序运行没有出现问题,运行正常呢?

没有发生问题是因为是现在的Windows XP操作系统对这类问题有非常健壮的解决方法,让我们避免了问题的发生。但是我们现在的程序不能保证在其他的操作系统能够运行正常!

  真正的解决方法是我们能够认识到问题所在,并在程序中加以避免。

技术分享

  如何避免多线程的窗体资源访问的安全问题呢?其实非常简单,有两种方法:

一种方法就是不管线程是否是用户界面线程,对用户界面资源的访问统一由委托完成;

另一种方法是在每个 Windows Forms 用户界面类中都有一个 InvokeRequired 属性,它用来标识当前线程是否能够直接访问窗体资源。我们只需要检查这个属性的值,只有当允许直接访问窗体资源时才直接访问相应的资源,否则,就需要通过 委托进行访问了。

  采用第一种安全的方法的代码片断如下:

// 显示进度条的委托声明
delegate void ShowProgressDelegate( int totalStep, int currentStep );

// 显示进度条
void ShowProgress( int totalStep, int currentStep )
{
_Progress.Maximum = totalStep;
_Progress.Value = currentStep;
}

// 执行任务的委托声明
delegate void RunTaskDelegate( int seconds );

// 执行任务
void RunTask( int seconds )
{
ShowProgressDelegate showProgress = new ShowProgressDelegate( ShowProgress );

// 每 1 / 4 秒 显示进度一次
for( int i = 0; i < seconds * 4; i++ )
{
Thread.Sleep( 250 );

// 显示进度条
this.Invoke( showProgress, new object[] { seconds * 4, i + 1 } );
}
}


采用第二种安全的方法的代码片断如下:

// 显示进度条的委托声明
delegate void ShowProgressDelegate( int totalStep, int currentStep );

// 显示进度条
void ShowProgress( int totalStep, int currentStep )
{
if( _Progress.InvokeRequired )
{
ShowProgressDelegate showProgress = new ShowProgressDelegate( ShowProgress );

// 为了避免工作线程被阻塞,采用异步调用委托
this.BeginInvoke( showProgress, new object[] { totalStep, currentStep } );
}
else
{
_Progress.Maximum = totalStep;
_Progress.Value = currentStep;
}
}

// 执行任务的委托声明
delegate void RunTaskDelegate( int seconds );

// 执行任务
void RunTask( int seconds )
{
// 每 1 / 4 秒 显示进度一次
for( int i = 0; i < seconds * 4; i++ )
{
Thread.Sleep( 250 );

// 显示进度条
ShowProgress( seconds * 4, i + 1 );
}
}


至此,我们用了几个示例说明了如何执行长任务、如何通过多线程异步处理任务进度的显示并解决了多线程的安全性等问题。希望能够给大家对理解多线程编程、委托的使用、异步调用等方面提供一些帮助,也希望能和大家进行进一步的沟通和交流。

[c#]多线程总结(结合进度条)(代码片段)

...状况。不可运行状态:已经调用Sleep方法已经调用Wait方法通过I/O操作阻塞死亡状态:当线程已完成执行或已中止时的状况。Thread常用方法:publicvoidInterrupt()   中断处于WaitSleepJoin线程状态的线程。pub 查看详情

多线程任务更新 1 个进度条 - UI C# WPF

】多线程任务更新1个进度条-UIC#WPF【英文标题】:Multiplethreadstasksupdating1progressbar-UIC#WPF【发布时间】:2021-07-1619:30:51【问题描述】:我一直在四处寻找有类似问题的人,但没有找到任何东西。我正在使用WPFUI编写C#应用程序。要... 查看详情

c#多线程往datagridview会造成假死,滚动条无法滚动

c#多线程往datagridview会造成假死,滚动条无法滚动我是新手,我希望得到帮助,求详细的代码和使用办法真的很紧急,谢谢了求详细的代码和使用办法首先多线程同时操作控件是不安全的,必须利用同步锁来控制线程之间的同步... 查看详情

c#如何根据文件数量控制进度条

...。如果你使用的StatusBar中的进度条的话,你可以不考虑多线程更新UI的问题,因为它本身已经在内部实现了外部线程更新UI控件的逻辑。但是如果你使用普通的Progressbar控件,那你就得自己处理这部分逻辑,因为控件只能在其所在... 查看详情

c#上位机开发——多线程+进度条的使用(代码片段)

1.界面设计2.使用多线程修改进度条引入多线程类库命名空间:usingSystem.Threading;将变量添加到Form1类:privateThreadth;将方法添加到Form1类:privatevoidThreadTask()intstp;intnewval;Randomrnd=newRandom();while(true)stp=this.progressBar1.Step... 查看详情

c#上位机开发——多线程+进度条的使用(代码片段)

1.界面设计2.使用多线程修改进度条引入多线程类库命名空间:usingSystem.Threading;将变量添加到Form1类:privateThreadth;将方法添加到Form1类:privatevoidThreadTask()intstp;intnewval;Randomrnd=newRandom();while(true)stp=this.progressBar1.Step... 查看详情

c#多线程编程(转)

...线程共享,线程不拥有资源。2、前台线程和后台线程:通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出 查看详情

c#winform多线程

...开新的子窗体,请问这种设计的winform程序需不需要用多线程,为什么?最好给个例子,不要复制粘贴!!!分数另付什么样的程序需要用到多线程一般在一些网络软件方面需要多线程,单单是管理软件什么的不需要。在网络软... 查看详情

主视图控制器外的多线程进度条并发问题

】主视图控制器外的多线程进度条并发问题【英文标题】:Multi-threadedprogressbarconcurrencyissueoutsidethemainviewcontroller【发布时间】:2015-10-2910:02:20【问题描述】:我在同一个线程和视图控制器中找到了很多进度条更新解决方案,但它... 查看详情

pyqt5进度条qprogressbar的使用/多线程更新/按钮美化/图片编码/开机自启动(代码片段)

...。项目背景我的项目是构建一个可视化的交互界面,通过界面上的按钮可调用后台的爬虫程序。因此,需要通过添加一个进度条来反映当前的爬取进度。进度条Pyqt5设有进度条控件QProgres 查看详情

c#多线程运行时出现主界面卡死现象如何解决?

...程,用来处理其他事务,如数据库的增删改查等,在3个线程同时开启时会出现主界面的“假死”现象,我尝试过将timer改为Thread,但是提示我不可以跨线程调用,加了将Thread加了委托之后可以实现跨线程了,但是还是会出现“假... 查看详情

带有进度条更新的 C++ 多线程套接字操作

】带有进度条更新的C++多线程套接字操作【英文标题】:C++Multithreadedsocketoperationwithprogressbarupdate【发布时间】:2014-06-1221:34:20【问题描述】:我有一个正在实现的MFCDLL。主线程创建一个进度条(CProgressCtrl),然后启动一个CWinThr... 查看详情

c#winform多线程异步委托进度条

求一个多线程异步委托实现进度条实时显示的代码示例。现在有一个按钮点击事件,点击按钮之后会对数据库进行进行访问获取数据,然后再对数据进行二次加工,之后再显示到DataGridView里面,这个过程时间比较长。我想让用户... 查看详情

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

...的用户体验。所以在大量数据操作的应用上,需要使用多线程来处理这种情况。在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单 查看详情

C# - 从线程更新 windows 窗体元素

...脑备份到U盘。我创建了一个从中调用方法的类。然后我通过一个单独的线程开始实际的备份。目前,我正在尝试通过此线程更改文本框和进度条。但是,它总是只立即显示第一个更改,而只有在程序运行后才显示其他进度。我... 查看详情

Xamarin Android C# 中的进度条和线程

】XamarinAndroidC#中的进度条和线程【英文标题】:ProgressbarandthreadinXamarinAndroidC#【发布时间】:2018-10-3023:53:08【问题描述】:我尝试使用这种方法加载我的SQL。当我点击按钮登录时,该方法正在工作,它显示了循环进度对话框,但... 查看详情

c#欢迎画面显示程序启动进度条,并自动打开主界面(代码片段)

...#xff1a;具体实现代码如下:软件界面加载时先启动后台线程进行延时操作,并实时显示到进度条上,待进度条完成后(也就是线程结束)程序会自动响应线程结束事件(注意这个响应事件是主线程上的,... 查看详情

实现winfrom进度条及进度信息提示,winfrom程序假死处理(代码片段)

方法一:使用线程    功能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法... 查看详情