c# 异步线程操作
发布网友
发布时间:2022-05-08 11:37
我来回答
共3个回答
热心网友
时间:2022-04-26 15:44
我觉得你对线程的理解还是不够的!如果我没有猜错,其实你只要的只是一个异步操作或是线程而已。
首先你先搞清几个概念: 委托/异步/事件/线程,这几个概念搞清楚了这后再来想线程的同步与异步的问题。
委托,这个是非常简单的概念,其实就是类似于C/C++中的函数指针而已,为了你更好的理解,你可以认为委托其实就是把成员方法参数化,然后可以把成员方法作为参数一样在其他成员方法中做为参数传入——这样你就可以理解什么是委托了。
异步,这个也非常简单,比如某个业务逻辑中要执行某个方法,而这个方法正常的情况下是执行出结果之后,代码才可以向下执行,这是同步,而异步时,这个成员方法并没有立即返回结果,程序则会继承向下执行,直接需要结果时进行堵塞等待异步方法的完成。问题在于你其实并不知道这个异步方法什么时候开始的,它的实现原理其实就是一个后台线程完成的。并将结果保存在IAsynResult中,等待你使用。
事件其实是一种特殊的委托!仅此而已,这个更好理解,它的实现是在类内部形成一个多播委托,程序在使用时可能通过事件句柄,绑定要执行的事件。
线程,这个当然就是一个线程的开辟,让多线程的机器同步执行,当然这个是由底层系统决定的,至于什么时候执行什么时候完成你完成不知道!
现在来看你的需求,你要执行的内容可能是不想影响其他程序运行的,如果任务只有一次,那么事件驱动对于你来说是绝对是正确的(但问题是我见过好多程序员,写类时只会写字段/属性/成员方法/索引器,他们并没有写过委托或事件,其实一个类是可以包含事件的,根据业务逻辑的分析,以事件驱动有时对于我们的业务来说是非常简单的,不会在类中定义事件的程序员绝对不是什么高手的)。
或者你的业务逻辑与本身类没有任何的关系或是较为松散,根据面向对象设计原理的话你不知道你的程序该放在哪个类下,或者他不属于任何类(面向对象的设计核心就是高内聚低耦合),那么这个业务可能是一个流业务或模块业务,那么此时,你应该开辟一个线程,线程中执行一个类的成员方法,然后使用事件驱动的方式思考这个问题,使用委托去修改界面中的属性值(松耦合的方式),这样才会达到较好的效果。
线程的同步与异步指的是线程间的调度的概念,与你的需求其实没有相关性的。而且你的需要描述的并不十分清楚,无法确定你到是需要异步/事件/线程。但是就线程本身来说,它与主线程(创建线程)之间其实没有关系的,所以不存在所谓与主线程之间的“异步/同步”关系。
比如:
Thread t = new Thread(new ThreadStart(MethodA));
t.start(); // 一定要知道,这个只是启动线程,实现上只是向系统注册,它只是相当于告诉系统,线程可以开始运行了,至于什么什么运行那要看系统了,并不是线程开始运行。
// other code in here;
t.Join(); // 当前线程(主线程进入阻塞,等待线程的完成
上边的例子中,t中其实是将一个委托给了线程,t.start()告诉线程线程可以开始了。
然后没有任何其他的等待,直接进入other code的运行。直到t.Join();则会阻击主线程,直到t线程完成后,代码才会向下执行。所以基本上来说,你不知道t中的代码还是other code谁先执行!这就是线程(其实线程要求的委托MethodA只是一种简写的形式必须是void返回值的)!异步其实也是这个道理,基本上根这个一模一样,只不过它是看起来是一个方法,实现也被系统封闭成了线程,但他会返回结果,所以异步方法使用IAsynResult或存放结果,直接你使用这个结果时,也会发生阻塞,等待异步的完成!
而事件则是一个多播的委托,做为一个接口开放,外部程序通过委托的方式绑定到多播委托上,你可以理解事件句柄其实是一个list列表,列表中存放的是一系列的委托,按照进入顺序(绑定)执行外部其些程序片段。所以事件一个的方法都是要带上事件源,事件参数两个参数的,如: public void XXXEvent(object sender, EventArgs e);其中sender就是事件源,而e就是该事件的参数。
事实上,菊花琏查询是一种比较耗时的操作,所以一般考虑事件进行驱动,比如某个类对象的成员执行完成时,向外提供一个OnCompleted的事件,那么,外部程序直接编写这个事件的,显然不再耗时。或者使用阻塞机制,让主线程等待子线程的完成。正是因为你这里说不清楚这一点儿的场景使用规则,所以无法判定你应该使用异步/事件驱动还是多线程。追问您好,非常感谢您的耐心回答,看了您的回答,我如洪湖灌顶般,就您的回答来看,我应该是需要写一个事件进行驱动,但是因为我这是无线循环的方法,故不清楚我该如何实现?
热心网友
时间:2022-04-26 17:02
直接上伪代码:
//在main函数或其他方法里面启动线程:
Thread t = new Thread(耗时操作方法名);
t.Start();
void 耗时操作方法名()
{
//...
this.Invoke((MethodInvoker)delegate
{
//更新界面的操作
});
Sleep(1000);
}