别的不多说先,先记下遇到的问题:如何在子线程中操作窗体上的控件

一般来说,直接在子线程中对窗体上的控件操作是会出现异常,这是由于子线程和运行窗体的线程是不同的空间,因此想要在子线程来操作窗体上的控件,是不可能简单的通过控件对象名来操作,但不是说不能进行操作,微软提供了Invoke的方法,其作用就是让子线程告诉窗体线程来完成相应的控件操作。
 
现在用一个用线程控制的进程条来说明,大致的步骤如下:
1.  创建Invoke函数,大致如下:
        ///<summary>
        /// Delegate function to be invoked by main thread
        ///</summary>
        private void InvokeFun()
        {
            if( prgBar.Value < 100 )
                prgBar.Value = prgBar.Value + 1;
        }
 
2.  子线程入口函数:
        ///<summary>
        /// Thread function interface
        ///</summary>
        private void ThreadFun()
        {
            //Create invoke method by specific function
            MethodInvoker mi = new MethodInvoker( this.InvokeFun );
 
            for( int i = 0; i < 100; i++ )
            {
                this.BeginInvoke( mi );
                Thread.Sleep( 100 );
            }
        }
 
3.  创建子线程:
            Thread thdProcess = new Thread( new ThreadStart( ThreadFun ) );
            thdProcess.Start();
 
       备注:
              using System.Threading;
              private System.Windows.Forms.ProgressBar prgBar;
及相关讨论:
knight94 发表于2006-04-21 09:21:00  IP: 218.71.239.*
首先,你在创建这个类的对象时,要把当前的窗体对象传进去(为了到时候能通过它调用其的方法)。
然后把
Thread thdProcess = new Thread( new ThreadStart( ThreadFun ) );
改成
Thread thdProcess = new Thread( new ThreadStart( yourObj.ThreadFun ) );
即可。

 
User 发表于2006-04-29 16:03:00  IP: 219.238.164.*
我想实现批量注册用户的功能,首先在文本域里录入用户信息(按照约定的规则),然后执行。
现在我希望在界面上有一个文本域滚动提示每个用户导入是否成功,失败的原因,另外可以有一个滚动条显示进度。

麻烦 knight94 ,指教。

 
knight94 发表于2006-05-01 13:17:00  IP: 218.71.239.*
to User

对于你的问题,参看我的例子就可以了,我的例子是如何滚动进度条,那么你可以在上面的基础上进行扩展,而且Invoke调用方法,也可以加参数,例如:
-------in your form class ------
public void ShowText( string sData )
{
//Handle "sData" here
}
--------in thread fun ----------
MethodInvoker mi = new MethodInvoker( this.ShowText );
this.BeginInvoke( mi, new object[]{ yourText } );

 
aicsharp 发表于2006-05-26 17:25:00  IP: 60.216.137.*
不错,msdn的解释太不中国了,光看那个根本不知道干什么的。他是这么解释的
“MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。

这是msdn for vs2005的解释。

 
DisonWorld 发表于2006-05-30 13:51:00  IP: 61.186.185.*
I have a question as the following:
foreach(int i in ...)
{
//the order is important, that is:
//DoSomthing(2) must be done after the DoSomething(1) is completed

DoSomething(i);
}

private void DoSomething(int i)
{
//In here, a function to upload file will be called,
//and it will be implemeted by using class Upload, who is inherited from BackgroundWorker and will call a WSE
// to upload the file, so the speed is a bit slow
}

So my question is how to make the DoSomthing(2) only begins when the DoSomthing(1) is finished.

 
knight94 发表于2006-05-30 14:04:00  IP: 218.71.239.*
to DisonWorld

you can reprace "BeginInvoke" method with "Invoke" method.

See difference between them in:
http://blog.csdn.net/Knight94/archive/2006/05/27/757351.aspx

 
DisonWorld 发表于2006-05-31 12:00:00  IP: 61.186.185.*
Hello Knight94,

I have tried the Invoke, but the ui seem to be dead, and the import order seems to wrong.
For example:
PackageA: no files to import
PackageB: need to import files
PackageC: no files to import
After the PackageA is finished, and the PackageB will start and begin import file, but even the PackageB has not been finished, the PackageC will start.
private delegate bool ImportSinglePackage();
private ImportSinglePackage importSinglePackage = null;

//The UI will call the BeginImport to start the importing
public BeginImport()
{
Cursor.Current = Cursors.WaitCursor;
this.importSinglePackage = new ImportSinglePackage(this.ImportBySinglePackage);

mImportingDataThread = new Thread(new ThreadStart(this.ImportPackages));
mImportingDataThread.Start();
}

private void ImportPackages()
{
bool IsAllPackagesHaveBeenImported = false;
do{
this.currentImportRecordKey = recordKeysToImport[recordsHasBeenImported];
Thread.Sleep(1000);
IsAllPackagesHaveBeenImported = (bool)this.Invoke(this.importSinglePackage, null);
}while (!IsAllPackagesHaveBeenImported);
}

private bool ImportBySinglePackage()
{
//ImportFiles will call the a class inherited from the BackgroundWorker to download/upload file

Thread threadImportFiles = new Thread(new ThreadStart(this.ImportFiles));
threadImportFiles.Start();
threadImportFiles.Join();
}

 
knight94 发表于2006-05-31 13:09:00  IP: 218.71.239.*
As the upper code, there is no return value in your function named "ImportBySinglePackage".

By the way, you should check the invoke's return value in your "ImportPackages" function.

 
tianjj 发表于2006-08-17 17:10:00  IP: 203.86.72.*
to:knight94

--------in thread fun ----------
MethodInvoker mi = new MethodInvoker( this.ShowText );
这个调用带有参数,好像有误。
提示showText重载与MethodInvoker不匹配。


 
tianjj 发表于2006-08-17 17:12:00  IP: 203.86.72.*
to:knight94

--------in thread fun ----------
MethodInvoker mi = new MethodInvoker( this.ShowText );
这个调用带有参数,好像有误。
提示showText重载与MethodInvoker不匹配。


 
tianjj 发表于2006-08-17 17:27:00  IP: 203.86.72.*
to:knight94
MethodInvoker mi = new MethodInvoker( this.ShowText );

这个调用带参数方法,好像有误,
显示showText重载与MethodInvoker不匹配。

 
knight94 发表于2006-08-17 18:07:00  IP: 218.71.239.*
to tianjj

参看:
http://blog.csdn.net/knight94/archive/2006/05/27/757351.aspx

 
knight94 发表于2006-08-17 18:10:00  IP: 218.71.239.*
to tianjj

MethodInvoker是一个delegate类型,你可以自己定义,例如:
public delegate int MyInvoker( string strValue );

MyInvoder mi = new MyInvoker( yourMethod );
this.Invoke( mi, new object[]{ "test" } );

 
菜鸟 发表于2006-08-23 16:29:00  IP: 219.140.184.*
进度条为什么不用TIMER控件来做?

 
knight94 发表于2006-08-23 17:48:00  IP: 218.71.239.*
Timer的交互性太差。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值