C# 线程之间的方法调用问题

问题描述

项目中有两A(),B()两个方法,当线程执行A方法时,在A中调用了BprivatevoidA(){doublex,y,z;//接收来自单片机的数据//执行速度非常快...........line.add(x,y);B(x,y,z);}privatevoidB(doublenx,doubleny,double,nz){//处理大量计算数据,延迟较大delay(100000)...........}上述两方法,首先执行A,代码很少,其中主要向tchart中画线,但B中有大量数据处理,比较耗时,会很拖延A的执行速率,界面显示数据时很卡.现在,为了不影响主界面的显示,想把B方法单独开一个线程,但问题来了,新开一个线程,B方法需要的参数x,y,z需要从A中来,而且怎样保证同步性(A执行一次,B也必须执行一次)不知道异步委托能不能行,但又不太熟悉,看了半天,资料也不太明白希望大家有什么好的解决方案,成分感激!

解决方案

解决方案二:
我也遇到了这问题,我接受到数据一边存一边显示。显示单独开了一个线程,定时去显示收到的数据。现在的问题就是无法保证同步。不知怎么解决。所以帮顶!
解决方案三:
引用1楼u010018424的回复:

我也遇到了这问题,我接受到数据一边存一边显示。显示单独开了一个线程,定时去显示收到的数据。现在的问题就是无法保证同步。不知怎么解决。所以帮顶!

我是在串口线程中,接收到数据时,先存储在数组中,再sendmessage在主窗体的WndProc中进行处理时调用了A方法用异步或委托都不好用
解决方案四:
首先,AB两部分都必须放在工作线程中,因为它们需要同步,只有它们都脱离了主线程才能避免界面的悬挂。至于这两个线程之间的同步,可以使用AutoResetEvent(信号量),或者lock(监视器、临界区)google生产者-消费者模式http://www.cnblogs.com/LoveJenny/archive/2011/05/31/2060777.html
解决方案五:
A产生的数据,先放到队列里,然后开N个线程去队列里取数据处理必须是多对一的形式,否则A快B慢,处理不过来,同步还是会卡住A
解决方案六:
该回复于2015-10-31 23:38:35被版主删除
解决方案七:
引用楼主wuhz520的回复:

项目中有两A(),B()两个方法,当线程执行A方法时,在A中调用了BprivatevoidA(){doublex,y,z;//接收来自单片机的数据//执行速度非常快...........line.add(x,y);B(x,y,z);}privatevoidB(doublenx,doubleny,double,nz){//处理大量计算数据,延迟较大delay(100000)...........}上述两方法,首先执行A,代码很少,其中主要向tchart中画线,但B中有大量数据处理,比较耗时,会很拖延A的执行速率,界面显示数据时很卡.现在,为了不影响主界面的显示,想把B方法单独开一个线程,但问题来了,新开一个线程,B方法需要的参数x,y,z需要从A中来,而且怎样保证同步性(A执行一次,B也必须执行一次)不知道异步委托能不能行,但又不太熟悉,看了半天,资料也不太明白希望大家有什么好的解决方案,成分感激!

可以将A产生的数据暂存到List或者队列,A存入完成后就返回;另外一个线程执行B的逻辑,这样能保证顺序,实现处理的异步化
解决方案八:
这个问题我之前遇到过,用队列比较合适,A方法用一个线程,将数据放入队列,B方法用一个线程,去队列读取数据执行,这样做效果不错。//循环读取数据库到队列publicvoidReader(Int32n){Stringid=String.Empty;Stringm_id;Stringh_id;Stringpic_name;Stringpic_url;Stringlist;Stringm1;Stringm2;Stringm3;sql_classconn=newsql_class();while(Stop==false){if(qu.Count<200){SqlDataReadersqlread=conn.getread("SELECTTOP2000,,,,,,,,FROMwhereid>"+key+"anderr="+n+"");if(sqlread.HasRows){while(sqlread.Read()){try{Monitor.Enter(qu);//锁定队列;id=sqlread.ToString();m_id=sqlread.ToString();h_id=sqlread.ToString();pic_name=sqlread.ToString();pic_url=sqlread.ToString();list=sqlread.ToString();m1=sqlread.ToString();m2=sqlread.ToString();m3=sqlread.ToString();qu.Enqueue(id+"#"+m_id+"#"+h_id+"#"+pic_name+"#"+pic_url+"#"+list+"#"+m1+"#"+m2+"#"+m3);}catch{}finally{Monitor.Exit(qu);//解锁队列}}key=Convert.ToInt32(id);}else{break;//终止任务循环}}Delay(2000);}}publicvoidrun(){Stringf=String.Empty;while(qu.Count>0&&Stop==false){try{Monitor.Enter(qu);//锁定队列;f=qu.Peek().ToString();qu.Dequeue();//删除队列第一条}catch{}finally{Monitor.Exit(qu);//解锁队列;}down_pic(f);//下载图片Delay(1000);}}

可以参考下,操作队列时需要锁定,你的B方法,可以用多线程处理,加快速度,我这个项目就是,用了10个线程来执行run()方法。
解决方案九:
拿到参数就开启线程处理,楼主说的一点都不冲突啊.
解决方案十:
引用8楼zhengnan2012的回复:

拿到参数就开启线程处理,楼主说的一点都不冲突啊.

不太明白你的意思,能详细讲解一下吗?谢谢!
解决方案十一:
引用6楼xian_wwq的回复:

可以将A产生的数据暂存到List或者队列,A存入完成后就返回;另外一个线程执行B的逻辑,这样能保证顺序,实现处理的异步化

初步实现思路也就只有这样,但我目前是将采集的数据,先存入到已经定义好的二维数组中,B方法中很多地方需要对这个数组中的数据进行二次计算,将这个数组改为List,不太好改。我的想法是,用一个累加器在A中计数,另一线程在B方法中计数,只要B中计数器不超过A中计数器就一直循环读取A存入的数据正在测试中。。。。。。
解决方案十二:
引用7楼phuai007的回复:

这个问题我之前遇到过,用队列比较合适,A方法用一个线程,将数据放入队列,B方法用一个线程,去队列读取数据执行,这样做效果不错。可以参考下,操作队列时需要锁定,你的B方法,可以用多线程处理,加快速度,我这个项目就是,用了10个线程来执行run()方法。

谢谢7楼的,受启发了
解决方案十三:
Task.WaitAll试看
解决方案十四:
先从业务流程重构,最后再说技术问题。你确定“A执行一次,B也必须执行一次”吗?这样你永远也不可能“看起来流畅”,而且堆积越来越多的垃圾(“队列”这个词儿只是一个噱头,解决不了问题)。通常会丢弃一些B,比如说仅执行“来得及执行的”最后一个B。不过这需要从实际的业务逻辑出发来设计。如果你懒得具体分析业务流程,就没有什么可能进行优化。一味地追求“技术”词儿,那么也根本不能用好什么技术。
解决方案十五:
引用11楼wuhz520的回复:

谢谢7楼的,受启发了

如果你原本被子线程调用的A,阻塞到一个“队列”,还要每一次放入队列时都延时2秒钟;而从队列上取出处理也是阻塞的,还要每一次都延时1秒钟,那么你就应该看到这跟你的程序要求“完全是一个地下一个天上”。
解决方案:
引用8楼zhengnan2012的回复:

拿到参数就开启线程处理,楼主说的一点都不冲突啊.

lz的出发点是“总共”只有两个线程的那种模式,而不是按需分配线程。
解决方案:
就你目前的情况,使用lock确实是可以解决问题的。定义一个全局的变量,在B中lock变量,在A中也lock变量。现在问题是如果A频繁被触发调用,而B又需要大量时间来计算,就会造成不匹配,不能完成你要求的A执行一次,B也执行一次的要求了。
解决方案:
你用笨法想A往仓库里放货物,B从仓库里取获取A放的快,B取的慢总有仓库放满了的时候要么A降低速度,B取出一个,A才能放进去一个要么货物就得丢弃一部分
解决方案:
要么就不能一个人放货,一个人取货既然取货慢,你多弄几个人,让取货快点不就得了
解决方案:
如果两个线程,然后A执行一次B执行一次那么就会是这种效果你连点三次,然后B后面慢慢执行.然后控制只有两处线程的方式,我感觉就是信号量的方式来控制.
解决方案:
如17#所说的.其它的方式还不好控制,包括Task.WaitAll也不好控制,这个只是保证在所有的线程执行完,但是要控制数量还是信号量方式好控制.
解决方案:
引用13楼sp1234的回复:

先从业务流程重构,最后再说技术问题。你确定“A执行一次,B也必须执行一次”吗?这样你永远也不可能“看起来流畅”,而且堆积越来越多的垃圾(“队列”这个词儿只是一个噱头,解决不了问题)。通常会丢弃一些B,比如说仅执行“来得及执行的”最后一个B。不过这需要从实际的业务逻辑出发来设计。如果你懒得具体分析业务流程,就没有什么可能进行优化。一味地追求“技术”词儿,那么也根本不能用好什么技术。

首先谢谢你的讲解,B中只是对A中存入数组的数据进行分析计算,得出相应的结果,每一个数据都不能丢的,再后面很多地方还要对数组进行操作。
解决方案:
引用16楼mjp1234airen4385的回复:

就你目前的情况,使用lock确实是可以解决问题的。定义一个全局的变量,在B中lock变量,在A中也lock变量。现在问题是如果A频繁被触发调用,而B又需要大量时间来计算,就会造成不匹配,不能完成你要求的A执行一次,B也执行一次的要求了。

有点不太明白你的意思,用lock虽然能保存A,B同步,但会拖慢了A的执行速度
解决方案:
引用18楼Z65443344的回复:

要么就不能一个人放货,一个人取货既然取货慢,你多弄几个人,让取货快点不就得了

如果开多个线程都去处理B的话,那么怎样保存几个线程在取数据时不重复,乱序呢?
解决方案:
用队列比较合适,A方法用一个线程,将数据放入队列,B方法用一个线程,去队列读取数据执行

学习了
解决方案:
引用22楼wuhz520的回复:

Quote: 引用16楼mjp1234airen4385的回复:
就你目前的情况,使用lock确实是可以解决问题的。定义一个全局的变量,在B中lock变量,在A中也lock变量。现在问题是如果A频繁被触发调用,而B又需要大量时间来计算,就会造成不匹配,不能完成你要求的A执行一次,B也执行一次的要求了。

有点不太明白你的意思,用lock虽然能保存A,B同步,但会拖慢了A的执行速度

就是你理解的意思。试试这个想法:每次当A从单片机接收数据完毕后,把数据插入一个列表List,数据包括:唯一ID(自己生产GUID),x,y,z,方法B执行完毕的回调函数(委托)。然后开启一个线程把前四个参数传入线程中,执行B方法,执行完毕,调用委托。(此处可以使用包含线程的类去实现)这样不影响A的执行,不影响UI,B执行完毕后,调用回调函数可以知道执行结果,并且可以根据执行再次更行UI。如果使用委托会影响UI的话,可以使用简单类型的参数,在B方法所在线程里根据ID设置参数,然后在UI里做个定时扫描来更新UI。
解决方案:
引用23楼wuhz520的回复:

如果开多个线程都去处理B的话,那么怎样保存几个线程在取数据时不重复,乱序呢?

保证不重复,加Lock啊,一次只能一个线程去取数据.反正是取数据其实很快,处理的慢而已,不会拖慢A的还是用出入库做比喻,入库和出库都要填单子,填单子其实很快,搬运慢为了保证数量的准确,必须进一个或者出一个就都要填单子,而不能乱哄哄的大家一起进去拿了就跑线程也是这样,A在放入队列,多个B在取出的时候,都要加lock,保证一次只有一个线程去操作队列B取出一个,就从队列里删除掉,让其他线程不会再取到一个同样的数据至于保证顺序,你可以让A在插入队列的时候加一个时间戳,B都处理完之后,按时间戳排序,就能够还原顺序还是出入库,如果箱子连个编号都没有,那么大家一起搬,有人搬的快,有人搬的慢,就没办法还原箱子原来堆放的顺序但是如果箱子有编号,就可以按原来的顺序重新堆放
解决方案:
我也遇到这个问题了,A方法需要频繁调用(A方法中也需要调用到B方法,B方法也需要用A方法的一些参数,B方法主要是用来界面显示处理数据的),B方法处理时间比较慢,调用A方法时需要等待B方法调用完,在此期间界面就进入假死了,频繁调用A方法时可以取最后一次A方法的参数,我想要的就是如何解决,调用B方法界面会进入假死的状态!

时间: 2024-10-15 21:09:44

C# 线程之间的方法调用问题的相关文章

YII contoller之间的方法调用 redirect

一个contoller CustomerController里怎么调用另一个controller里的action,Acontoller调用SiteContoller的actionShow($id), url显示上是Customer/index Java代码   $control=Yii::app()->runController('site/show/id/2');   不带参数的actionShow() Java代码   $control=Yii::app()->runController(

Java编程那些事儿54—方法调用

7.4 方法调用 方法声明是创建一个新的功能,声明出来的方法在需要的时候可以通过调用执行该方法的功能,方法只有被调用才能被执行. 在Java程序中有一个基本的main方法,其方法声明如下: public static void main(String[] args) 该方法包含在开始的代码框架中,这是一个特殊的方法.Java语法规定,J2SE的代码都从该方法开始执行,如果一个代码中没有main方法,则该代码不能被直接运行.所以main方法也称作J2SE程序的入口方法,在运行程序时,自动调用对应代

如何在普通类实例的线程过程中,同步调用执行在类实例自身所在的原来的那个线程中的方法

问题描述 如何在普通类实例的线程过程中,同步调用执行在类实例自身所在的原来的那个线程中的方法如后代码,是一个常见的实例,讲的是通过Control.Invoke在线程函数中,同步调用窗体主线程中的Form1实例的普通方法txt.但问题是,很多时候我们自己自定义的类,并不是从Control类继承的,从而也没有这个功能的Invoke方法供调用,这种类要怎么设计呢?虽然说用的示例代码是vb.net的,但严格来说,这个和语言无关,是一个.net开发的基本问题.ImportsSystemImportsSys

C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)

本文转载:http://www.csframework.com/archive/2/arc-2-20110805-1771.htm 文章侧重点主要是讨论"窗体"与"窗体"之间方法的调用,以及"MDI父窗体"与"Chilid子窗体"之间如何相互的调用方法. C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用) 看似一个简单的功能需求,其实很多初学者处理不好的,很多朋友会这么写: C# Code: //父窗体是是frmPare

java线程间通信[实现不同线程之间的消息传递(通信),生产者和消费者模型]

线程通信,线程之间的消息传递: 多个线程在操作同一个资源,但对共享资源的操作动作不同:它们共享同一个资源,互为条件,相互依赖,相互通信让任务向前推进. 线程的同步,可以解决并发更新同一个资源,实现线程同步;但不能用来实现线程间的消息传递. 线程通信生产者和消费者和仓库是个典型模型: 生产者:没有生产之前通知消费者等待,生产产品结束之后,马上通知消费者消费 消费者:没有消费之前通知生产者等待,消费产品结束之后,通知生产者继续生产产品以供消费 线程通信:使用java中Object中提供的: publ

理解iOS多线程应用的开发以及线程的创建方法_IOS

一.进程和线程1.什么是进程   进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过"活动监视器"可以查看Mac系统中所开启的进程   2.什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 3.线程的串行   1个线程

VC中利用多线程技术实现线程之间的通信

文章来源:[url]http://www.programfan.com/article/showarticle.asp?id=2951[/url] 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.

线程之间的通信(thread signal)

线程通信的目的是为了能够让线程之间相互发送信号.另外,线程通信还能够使得线程等待其它线程的信号,比如,线程B可以等待线程A的信号,这个信号可以是线程A已经处理完成的信号. 通过共享对象通信 有一个简单的实现线程之间通信的方式,就是在共享对象的变量中设置信号值.比如线程A在一个同步块中设置一个成员变量hasDataToProcess值为true,而线程B同样在一个同步块中读取这个成员变量.下面例子演示了一个持有信号值的对象,并提供了设置信号值和获取信号值的同步方法: public class My

Handler实现线程之间的通信下载文件动态更新进度条

1. 原理 每一个线程对应一个消息队列MessageQueue,实现线程之间的通信,可通过Handler对象将数据装进Message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息. 2. Message 初始化:一般使用Message.obtain()方法获取一个消息对象,该方法会检查Message对象池中是否存在可重复利用的对象,若无,才会new一个新对象. what:相当于Message的标识符,区别于其它消息. arg1.arg2:int类型,可传递整数. obj:objec